Merge "Make tests more reliable by cleaning up worker threads on cancelation. b/17888343" into lmp-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 33531c8..ce67d37 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -15,6 +15,8 @@
cts_security_apps_list := \
CtsAppAccessData \
CtsAppWithData \
+ CtsDocumentProvider \
+ CtsDocumentClient \
CtsExternalStorageApp \
CtsInstrumentationAppDiffCert \
CtsPermissionDeclareApp \
@@ -40,6 +42,22 @@
CtsWriteExternalStorageApp \
CtsMultiUserStorageApp
+cts_security_keysets_list := \
+ CtsKeySetTestApp \
+ CtsKeySetPermDefSigningA \
+ CtsKeySetPermDefSigningB\
+ CtsKeySetPermUseSigningA \
+ CtsKeySetPermUseSigningB \
+ CtsKeySetSigningAUpgradeA \
+ CtsKeySetSigningBUpgradeA \
+ CtsKeySetSigningAUpgradeAAndB \
+ CtsKeySetSigningAUpgradeAOrB \
+ CtsKeySetSigningAUpgradeB \
+ CtsKeySetSigningBUpgradeB \
+ CtsKeySetSigningAAndBUpgradeA \
+ CtsKeySetSigningAAndCUpgradeB \
+ CtsKeySetSigningAUpgradeNone
+
cts_support_packages := \
CtsAccelerationTestStubs \
CtsAppTestStubs \
@@ -59,7 +77,8 @@
TestDeviceSetup \
CtsUiAutomatorApp \
CtsUsbSerialTestApp \
- $(cts_security_apps_list)
+ $(cts_security_apps_list) \
+ $(cts_security_keysets_list)
cts_external_packages := \
com.replica.replicaisland \
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index f37e1fa..bba42ad 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -349,17 +349,6 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
</activity>
- <activity android:name=".bluetooth.BleScannerPrivacyMacActivity"
- android:label="@string/ble_privacy_mac_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleScannerTestActivity" />
- </activity>
-
<activity android:name=".bluetooth.BleScannerPowerLevelActivity"
android:label="@string/ble_power_level_name"
android:configChanges="keyboardHidden|orientation|screenSize">
@@ -393,17 +382,6 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
</activity>
- <activity android:name=".bluetooth.BleAdvertiserPrivacyMacActivity"
- android:label="@string/ble_privacy_mac_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleAdvertiserTestActivity" />
- </activity>
-
<activity android:name=".bluetooth.BleAdvertiserPowerLevelActivity"
android:label="@string/ble_power_level_name"
android:configChanges="keyboardHidden|orientation|screenSize">
@@ -835,6 +813,8 @@
<category android:name="android.cts.intent.category.MANUAL_TEST"/>
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
+ <meta-data android:name="test_excluded_features"
+ android:value="android.hardware.type.television:android.software.leanback" />
</activity>
<activity android:name=".sensors.SensorIntegrationTestsActivity"
diff --git a/apps/CtsVerifier/res/layout/ble_advertiser_privacy_mac.xml b/apps/CtsVerifier/res/layout/ble_advertiser_privacy_mac.xml
deleted file mode 100644
index 1c68b98..0000000
--- a/apps/CtsVerifier/res/layout/ble_advertiser_privacy_mac.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
- >
- <TextView android:text="@string/ble_advertiser_privacy_mac_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <Button android:id="@+id/ble_privacy_mac_start"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/ble_advertiser_start"
- />
- <Button android:id="@+id/ble_privacy_mac_stop"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/ble_advertiser_stop"
- />
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml b/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml
index 970b03a..b240db6 100644
--- a/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml
+++ b/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml
@@ -22,11 +22,14 @@
<TextView android:text="@string/ble_scanner_power_level_instruction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:id="@+id/ble_scanner_power_level_instruction"
/>
<LinearLayout android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_below="@+id/ble_scanner_power_level_instruction"
android:layout_centerInParent="true"
+ android:padding="10dp"
>
<LinearLayout android:orientation="horizontal"
android:layout_width="match_parent"
@@ -156,6 +159,9 @@
android:layout_height="wrap_content"
/>
</LinearLayout>
+ <TextView android:id="@+id/ble_timer"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
</LinearLayout>
<include android:layout_width="match_parent"
diff --git a/apps/CtsVerifier/res/layout/ble_scanner_privacy_mac.xml b/apps/CtsVerifier/res/layout/ble_scanner_privacy_mac.xml
deleted file mode 100644
index cad78a3..0000000
--- a/apps/CtsVerifier/res/layout/ble_scanner_privacy_mac.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
- >
-
- <TextView
- android:text="@string/ble_scanner_privacy_mac_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <TextView android:text="@string/ble_address"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- />
- <TextView android:id="@+id/ble_mac_address"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- />
- </LinearLayout>
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <TextView android:id="@+id/ble_mac_count"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <TextView android:id="@+id/ble_resp_count"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/ble_mac_count"
- />
- </LinearLayout>
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <TextView android:id="@+id/ble_timer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- </LinearLayout>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 879443f..3b74e52 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -238,7 +238,7 @@
<string name="ble_power_level_info">BLE Advertiser advertises in 4 different power levels. Scanner should receive them in different strength of Rssi, cannot receive weak signals beyond several feet.</string>
<string name="ble_advertiser_power_level_instruction">Click start to start multi-advertising. Data packets are advertised in 4 different power levels. You may receive message that this device does not support multi advertising. If advertiser does not advertise in 4 power levels, neither you receive the error message, you may not stop the advertising in previous test, or this device does not support 4 advertisers at the same time. Try rebooting the device and run the test to free those advertisers in use.</string>
<string name="ble_advertiser_scan_filter_name">BLE Hardware Scan Filter</string>
- <string name="ble_advertiser_scan_filter_info">BLE Advertiser advertises with 2 different data separately. One can wake up the scanner, the other cannot.</string>
+ <string name="ble_advertiser_scan_filter_info">BLE Advertiser advertises with 2 different data separately. One can wake up the scanner, the other cannot. This test cares about behavior on scanner only.</string>
<string name="ble_advertiser_scannable">Scannable advertising</string>
<string name="ble_advertiser_scannable_instruction">Start scannable advertising, expect scanner consume more power on Monsoon monitor, or see log of GattService from scanner logcat.</string>
<string name="ble_advertiser_unscannable">Unscannble advertising</string>
@@ -256,7 +256,7 @@
<string name="ble_low">Low</string>
<string name="ble_medium">Medium</string>
<string name="ble_high">High</string>
- <string name="ble_scanner_power_level_instruction">Count: Ultra low < low < medium < high\nRssi: Ultra low < low < medium < high\nDistance to see count freezing: Ultra low < low < medium < high\nA common error is ultra low, low and medium behave similarly, with similar rssi, freeze at similar distance.</string>
+ <string name="ble_scanner_power_level_instruction">Count: Ultra low < low < medium < high\nRssi: Ultra low < low < medium < high\nDistance to see count freezing: Ultra low < low < medium < high\nA common error is ultra low, low and medium behave similarly, with similar rssi, freeze at similar distance.\n\n All power level receive a different mac address. After 15 mins, a green text "Get a new Mac address" will show up.</string>
<string name="ble_scanner_scan_filter_name">BLE Hardware Scan Filter</string>
<string name="ble_scanner_scan_filter_info">Lock the screen of scanner, and connect to monsoon. It will not wake up when advertiser is advertising unscannable, and scanner is scanning with filter.</string>
<string name="ble_scanner_scan_filter_instruction">For monsoon test:\n\tClick scan with filter, lock the screen, connect to monsoon. It will not wake up when advertiser is advertising unscannable data packets, but will show a peak in power usage when advertiser is advertising scannable data.\nFor logcat test:\n\tClick scan with filter, logcat the scanner. No data will be received by GattService when advertiser is advertising unscannable data.</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserPrivacyMacActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserPrivacyMacActivity.java
deleted file mode 100644
index 87879bd..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserPrivacyMacActivity.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2013 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.verifier.bluetooth;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.Toast;
-
-public class BleAdvertiserPrivacyMacActivity extends PassFailButtons.Activity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_advertiser_privacy_mac);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.ble_privacy_mac_name,
- R.string.ble_privacy_mac_info, -1);
-
- ((Button) findViewById(R.id.ble_privacy_mac_start))
- .setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(BleAdvertiserPrivacyMacActivity.this,
- BleAdvertiserService.class);
- intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
- BleAdvertiserService.COMMAND_START_ADVERTISE);
- startService(intent);
- }
- });
- ((Button) findViewById(R.id.ble_privacy_mac_stop))
- .setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- stopAdvertising();
- }
- });
-
- }
-
- @Override
- public void onResume() {
- super.onResume();
- IntentFilter filter = new IntentFilter();
- filter.addAction(BleAdvertiserService.BLE_START_ADVERTISE);
- filter.addAction(BleAdvertiserService.BLE_STOP_ADVERTISE);
- registerReceiver(onBroadcast, filter);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- unregisterReceiver(onBroadcast);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- stopAdvertising();
- }
-
- private void showMessage(String msg) {
- Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
- }
-
- private void stopAdvertising() {
- Intent intent = new Intent(BleAdvertiserPrivacyMacActivity.this,
- BleAdvertiserService.class);
- intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
- BleAdvertiserService.COMMAND_STOP_ADVERTISE);
- startService(intent);
- }
-
- private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- switch (intent.getAction()) {
- case BleAdvertiserService.BLE_START_ADVERTISE:
- showMessage("Start advertising, please hold for 15 min");
- break;
- case BleAdvertiserService.BLE_STOP_ADVERTISE:
- showMessage("Stop advertising");
- break;
- }
- }
- };
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java
index 925c766..a6489c1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java
@@ -19,6 +19,7 @@
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
+import java.lang.Math;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
@@ -29,6 +30,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
+import android.os.CountDownTimer;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
@@ -44,6 +46,10 @@
private Map<Integer, Integer> mCount;
private int[] mPowerLevel;
+ private TextView mTimerText;
+ private CountDownTimer mTimer;
+ private static final long REFRESH_MAC_TIME = 930000; // 15.5 min
+
private static final int[] POWER_DBM = {-21, -15, -7, 1, 9};
@Override
@@ -54,9 +60,25 @@
setInfoResources(R.string.ble_power_level_name,
R.string.ble_power_level_info, -1);
- mCount = new HashMap<Integer, Integer>();
+ mTimerText = (TextView)findViewById(R.id.ble_timer);
+ mTimer = new CountDownTimer(REFRESH_MAC_TIME, 1000) {
+ @Override
+ public void onTick(long millis) {
+ int min = (int)millis / 60000;
+ int sec = ((int)millis / 1000) % 60;
+ mTimerText.setText(min + ":" + sec);
+ }
+
+ @Override
+ public void onFinish() {
+ mTimerText.setTextColor(getResources().getColor(R.color.red));
+ mTimerText.setText("Time is up!");
+ }
+ };
+
mRssiText = new HashMap<Integer, TextView>();
mCountText = new HashMap<Integer, TextView>();
+ mCount = null;
mMacText = new HashMap<Integer, TextView>();
mSetPowerText = new HashMap<Integer, TextView>();
mPowerLevel = new int[]{AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
@@ -64,9 +86,6 @@
AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM,
AdvertiseSettings.ADVERTISE_TX_POWER_HIGH};
- for (int i : mPowerLevel) {
- mCount.put(i, 0);
- }
mMacText.put(AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
(TextView)findViewById(R.id.ble_ultra_low_mac));
mMacText.put(AdvertiseSettings.ADVERTISE_TX_POWER_LOW,
@@ -114,6 +133,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(BleScannerService.BLE_POWER_LEVEL);
+ filter.addAction(BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE);
registerReceiver(onBroadcast, filter);
}
@@ -135,26 +155,43 @@
switch (intent.getAction()) {
case BleScannerService.BLE_POWER_LEVEL:
int powerLevelBit = intent.getIntExtra(
- BleScannerService.EXTRA_POWER_LEVEL_BIT, -1);
+ BleScannerService.EXTRA_POWER_LEVEL_BIT, -1);
int powerLevel = intent.getIntExtra(BleScannerService.EXTRA_POWER_LEVEL, -2);
if (powerLevelBit < 0 || powerLevelBit > 3) {
- Toast.makeText(context, "Invalid power level", Toast.LENGTH_SHORT).show();
- break;
+ Toast.makeText(context, "Invalid power level", Toast.LENGTH_SHORT).show();
+ break;
+ }
+
+ if (mCount == null) {
+ mCount = new HashMap<Integer, Integer>();
+ for (int i : mPowerLevel) {
+ mCount.put(i, 0);
+ }
+ mTimer.start();
}
Integer t = mCount.get(powerLevelBit) + 1;
mCount.put(powerLevelBit, t);
mCountText.get(powerLevelBit).setText(t.toString());
+
mMacText.get(powerLevelBit)
.setText(intent.getStringExtra(BleScannerService.EXTRA_MAC_ADDRESS));
mRssiText.get(powerLevelBit)
.setText(intent.getStringExtra(BleScannerService.EXTRA_RSSI));
- if (POWER_DBM[powerLevelBit] == powerLevel) {
+ if (Math.abs(POWER_DBM[powerLevelBit] - powerLevel) < 2) {
mSetPowerText.get(powerLevelBit).setText("Valid power level");
} else {
mSetPowerText.get(powerLevelBit)
.setText("Unknown BLe advertise tx power: " + powerLevel);
}
break;
+ case BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE:
+ Toast.makeText(context, "New MAC address detected", Toast.LENGTH_SHORT)
+ .show();
+ mTimerText.setTextColor(getResources().getColor(R.color.green));
+ mTimerText.append(" Get new MAC address.");
+ mTimer.cancel();
+ getPassButton().setEnabled(true);
+ break;
}
}
};
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPrivacyMacActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPrivacyMacActivity.java
deleted file mode 100644
index b7e4129..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPrivacyMacActivity.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2013 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.verifier.bluetooth;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.CountDownTimer;
-import android.widget.TextView;
-import android.widget.Toast;
-
-public class BleScannerPrivacyMacActivity extends PassFailButtons.Activity {
-
- private static final String TAG = "BleScannerPrivacyMac";
-
- private int mMacCount;
- private int mRespCount;
- private TextView mMacText;
- private TextView mCountText;
- private TextView mRespText;
- private TextView mTimerText;
- private CountDownTimer mTimer;
- private static final long REFRESH_MAC_TIME = 930000; // 15.5 min
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_scanner_privacy_mac);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.ble_privacy_mac_name,
- R.string.ble_privacy_mac_info, -1);
- getPassButton().setEnabled(false);
- mMacCount = 0;
- mRespCount = 0;
- mMacText = (TextView)findViewById(R.id.ble_mac_address);
- mCountText = (TextView)findViewById(R.id.ble_mac_count);
- mRespText = (TextView)findViewById(R.id.ble_resp_count);
- mTimerText = (TextView)findViewById(R.id.ble_timer);
-
- mTimer = new CountDownTimer(REFRESH_MAC_TIME, 1000) {
- @Override
- public void onTick(long millis) {
- int min = (int)millis / 60000;
- int sec = ((int)millis / 1000) % 60;
- mTimerText.setText(min + ":" + sec);
- }
-
- @Override
- public void onFinish() {
- mTimerText.setTextColor(getResources().getColor(R.color.red));
- mTimerText.setText("Time is up!");
- stop();
- }
- };
-
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE);
- filter.addAction(BleScannerService.BLE_MAC_ADDRESS);
- filter.addAction(BleScannerService.BLE_SCAN_RESP);
- registerReceiver(onBroadcast, filter);
-
- if (mMacCount == 0) {
- Intent intent = new Intent(this, BleScannerService.class);
- intent.putExtra(BleScannerService.EXTRA_COMMAND, BleScannerService.COMMAND_PRIVACY_MAC);
- startService(intent);
- }
- }
-
-
- private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- switch (intent.getAction()) {
- case BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE:
- mMacText.append(", " + intent.getStringExtra(BleScannerService.EXTRA_MAC_ADDRESS));
- Toast.makeText(context, "New MAC address detected", Toast.LENGTH_SHORT).show();
- mTimerText.setTextColor(getResources().getColor(R.color.green));
- mTimerText.append(" Get new MAC address.");
- mTimer.cancel();
- getPassButton().setEnabled(true);
- break;
- case BleScannerService.BLE_MAC_ADDRESS:
- if (mMacCount == 0) {
- mMacText.setText(intent.getStringExtra(BleScannerService.EXTRA_MAC_ADDRESS));
- mTimer.start();
- }
- mMacCount++;
- mCountText.setText("Count: " + mMacCount);
- break;
- case BleScannerService.BLE_SCAN_RESP:
- mRespCount++;
- mRespText.setText("Response: " + mRespCount);
- break;
- }
- }
- };
-
- @Override
- public void onPause() {
- super.onPause();
- unregisterReceiver(onBroadcast);
- }
-
- private void stop() {
- stopService(new Intent(this, BleScannerService.class));
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- stop();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
index c8e7953..d3d96ac 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
@@ -19,6 +19,7 @@
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
@@ -44,7 +45,6 @@
public static final boolean DEBUG = true;
public static final String TAG = "BleScannerService";
- public static final int COMMAND_PRIVACY_MAC = 0;
public static final int COMMAND_POWER_LEVEL = 1;
public static final int COMMAND_SCAN_WITH_FILTER = 2;
public static final int COMMAND_SCAN_WITHOUT_FILTER = 3;
@@ -105,21 +105,6 @@
int command = intent.getIntExtra(EXTRA_COMMAND, -1);
switch (command) {
- case COMMAND_PRIVACY_MAC:
- filters.add(new ScanFilter.Builder()
- .setManufacturerData(MANUFACTURER_TEST_ID,
- new byte[]{MANUFACTURER_TEST_ID, 0})
- .setServiceData(new ParcelUuid(BleAdvertiserService.PRIVACY_MAC_UUID),
- BleAdvertiserService.PRIVACY_MAC_DATA)
- .build());
- filters.add(new ScanFilter.Builder()
- .setManufacturerData(MANUFACTURER_TEST_ID,
- new byte[]{MANUFACTURER_TEST_ID, 0})
- .setServiceData(new ParcelUuid(BleAdvertiserService.SCAN_RESP_UUID),
- BleAdvertiserService.PRIVACY_RESPONSE)
- .build());
- settingBuilder.setScanMode(ScanSettings.SCAN_MODE_BALANCED);
- break;
case COMMAND_POWER_LEVEL:
filters.add(new ScanFilter.Builder()
.setManufacturerData(MANUFACTURER_TEST_ID,
@@ -182,21 +167,6 @@
String mac = result.getDevice().getAddress();
Map<ParcelUuid, byte[]> serviceData = record.getServiceData();
- if (serviceData.get(new ParcelUuid(BleAdvertiserService.PRIVACY_MAC_UUID)) != null) {
- Intent privacyIntent = new Intent(BLE_MAC_ADDRESS);
- privacyIntent.putExtra(EXTRA_MAC_ADDRESS, mac);
- sendBroadcast(privacyIntent);
-
- if (mOldMac == null) {
- mOldMac = mac;
- } else if (!mOldMac.equals(mac)) {
- mOldMac = mac;
- Intent newIntent = new Intent(BLE_PRIVACY_NEW_MAC_RECEIVE);
- newIntent.putExtra(EXTRA_MAC_ADDRESS, mac);
- sendBroadcast(newIntent);
- }
- }
-
if (serviceData.get(new ParcelUuid(BleAdvertiserService.POWER_LEVEL_UUID)) != null) {
byte[] data =
serviceData.get(new ParcelUuid(BleAdvertiserService.POWER_LEVEL_UUID));
@@ -207,6 +177,18 @@
powerIntent.putExtra(EXTRA_RSSI, new Integer(result.getRssi()).toString());
powerIntent.putExtra(EXTRA_POWER_LEVEL_BIT, (int)data[2]);
sendBroadcast(powerIntent);
+
+ // Check privacy mac.
+ if (data[2] == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) {
+ String newMac = result.getDevice().getAddress();
+ if (mOldMac == null) {
+ mOldMac = newMac;
+ } else if (!mOldMac.equals(mac)) {
+ mOldMac = newMac;
+ Intent newIntent = new Intent(BLE_PRIVACY_NEW_MAC_RECEIVE);
+ sendBroadcast(newIntent);
+ }
+ }
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
index f19142f..d325b65 100755
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
@@ -18,7 +18,6 @@
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
-import android.app.Activity;
import android.app.AlertDialog;
import android.graphics.Bitmap;
import android.graphics.Color;
@@ -47,9 +46,7 @@
import android.widget.Toast;
import java.io.IOException;
-import java.lang.InterruptedException;
import java.lang.Math;
-import java.lang.Thread;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Comparator;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
index d71dca2..178a811 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
@@ -69,7 +69,7 @@
private List<SelectableResolution> mSupportedResolutions;
private ArrayAdapter<SelectableResolution> mAdapter;
- private int mCameraId;
+ private SelectableResolution mSelectedResolution;
private Camera mCamera;
private Size mSurfaceSize;
private boolean mCameraInitialized = false;
@@ -165,12 +165,7 @@
AdapterView<?> parent, View view, int position, long id) {
if (mSupportedResolutions != null) {
SelectableResolution resolution = mSupportedResolutions.get(position);
-
- switchToCamera(resolution.cameraId, false);
-
- Camera.Parameters params = mCamera.getParameters();
- params.setPictureSize(resolution.width, resolution.height);
- mCamera.setParameters(params);
+ switchToCamera(resolution, false);
// It should be guaranteed that the FOV is correctly updated after setParameters().
mReportedFovPrePictureTaken = mCamera.getParameters().getHorizontalViewAngle();
@@ -376,7 +371,7 @@
public void onCancel(DialogInterface arg0) {
// User cancelled preview size selection.
mPreviewSizes = null;
- switchToCamera(mCameraId, true);
+ switchToCamera(mSelectedResolution, true);
}
}).
setSingleChoiceItems(choices, 0, new DialogInterface.OnClickListener() {
@@ -389,7 +384,7 @@
if (mPreviewSizeCamerasToProcess.isEmpty()) {
// We're done, re-initialize camera.
- switchToCamera(mCameraId, true);
+ switchToCamera(mSelectedResolution, true);
} else {
// Process other cameras.
showNextDialogToChoosePreviewSize();
@@ -415,7 +410,7 @@
// Either use chosen preview size for current camera or automatically
// choose preview size based on view dimensions.
- Size selectedPreviewSize = (mPreviewSizes != null) ? mPreviewSizes[mCameraId] :
+ Size selectedPreviewSize = (mPreviewSizes != null) ? mPreviewSizes[mSelectedResolution.cameraId] :
getBestPreviewSize(mSurfaceSize.width, mSurfaceSize.height, params);
if (selectedPreviewSize != null) {
params.setPreviewSize(selectedPreviewSize.width, selectedPreviewSize.height);
@@ -427,19 +422,20 @@
private void startPreview() {
if (mCameraInitialized && mCamera != null) {
- setCameraDisplayOrientation(this, mCameraId, mCamera);
+ setCameraDisplayOrientation(this, mSelectedResolution.cameraId, mCamera);
mCamera.startPreview();
mPreviewActive = true;
}
}
- private void switchToCamera(int cameraId, boolean initializeCamera) {
+ private void switchToCamera(SelectableResolution resolution, boolean initializeCamera) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
}
- mCameraId = cameraId;
- mCamera = Camera.open(cameraId);
+
+ mSelectedResolution = resolution;
+ mCamera = Camera.open(mSelectedResolution.cameraId);
if (initializeCamera){
initializeCamera();
@@ -472,7 +468,7 @@
* Set the common camera parameters on the given camera and returns the
* parameter object for further modification, if needed.
*/
- private static Camera.Parameters setCameraParams(Camera camera) {
+ private Camera.Parameters setCameraParams(Camera camera) {
// The picture size is taken and set from the spinner selection
// callback.
Camera.Parameters params = camera.getParameters();
@@ -480,6 +476,7 @@
params.setJpegQuality(100);
params.setFocusMode(getFocusMode(camera));
params.setZoom(0);
+ params.setPictureSize(mSelectedResolution.width, mSelectedResolution.height);
return params;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
index 6881bea..9204de3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
@@ -19,32 +19,20 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageFormat;
-import android.graphics.Matrix;
import android.hardware.Camera;
import android.os.Bundle;
-import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
-import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
import com.android.cts.verifier.TestResult;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
import java.util.TreeSet;
/**
diff --git a/hostsidetests/appsecurity/certs/keysets/README b/hostsidetests/appsecurity/certs/keysets/README
new file mode 100644
index 0000000..251dab1
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/README
@@ -0,0 +1,9 @@
+# Generated with:
+development/tools/make_key cts-keyset-test-a '/CN=unit_test_a'
+development/tools/make_key cts-keyset-test-b '/CN=unit_test_b'
+development/tools/make_key cts-keyset-test-c '/CN=unit_test_c'
+
+# Display public key (for use in Manifest) with:
+openssl x509 -in cts-keyset-test-a.x509.pem -inform PEM -pubkey
+openssl x509 -in cts-keyset-test-b.x509.pem -inform PEM -pubkey
+openssl x509 -in cts-keyset-test-c.x509.pem -inform PEM -pubkey
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.pk8 b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.pk8
new file mode 100644
index 0000000..b0dd6a3
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.x509.pem b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.x509.pem
new file mode 100644
index 0000000..cee8227
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIJAJ126KYAFwgTMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMMEWN0cy1rZXlzZXQtdGVzdC1hMB4XDTE0MDkxMTAwNDQ0OFoXDTQyMDEyNzAw
+NDQ0OFowHDEaMBgGA1UEAwwRY3RzLWtleXNldC10ZXN0LWEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDB/nMluW9hIHtibuiv/saCAAC7uantGvKQ8mxe
+Gh3x2gWFVPmzt4XcDgwITnm+8A0/se/AzDZv5PqrHs+rRUm1ttIO2UEcG0hzjs+O
+rQKwODn3QFRyAqns90n0npRWC3MOdXpwYSleZJqDexj6WqJbTjK0+EJXDNhNYZ1h
+735MiXjtwGu95F8s6Uaty4VB77MJOYMWrMEoJEcr1vuXk8Na9dfKDrlS78wFQD9N
+lY7R8So6XFkb+efoNQpAuE92YlFdYndaow0yEkYP6cq2SZ1fvTfFGqaDiH7qDRLs
+z1jchDY1QbLDTkBjMKC4cH8y/q5UiJbrn3ClvJvjlOAobdSFAgMBAAGjUDBOMB0G
+A1UdDgQWBBTev2AuCLdXO85IFqwy6rIV+wUokjAfBgNVHSMEGDAWgBTev2AuCLdX
+O85IFqwy6rIV+wUokjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCS
+8bjQglLYCNMFHc6AeAvSfu/j9rbZNTmK+0SCCUYbb4s1LoMNQ1hmHhs+nrmrOTe9
+3VgaKPUz2h6+toOM5KhMpkxDUHxe+VKJF4V+TRxMWZbPaz0wgj21FKcV7u5wnWnj
+i08O9dzksIzkD9UrOaxlExG20YFJE9kizoR0i2mZJWhR+1g6SeNc7PeaUnEI344G
+LfSDGt27EqZhmZ1BhJ4lRRUMq3TJFEfdFeVc3z+AgtyrZnxc7jNQ0PFdOXDtzz6B
+iC6AmFsMC/mRettVxjTeOpLo+12UE7FwO+wRa57pNGtljzlKz+DGBAZxi+gLcRDf
+i0TJhPAB4dFqrDgxr+4Y
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.pk8 b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.pk8
new file mode 100644
index 0000000..bf6dee1
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.x509.pem b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.x509.pem
new file mode 100644
index 0000000..912861f
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIJAOZwpbLsHooSMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMMEWN0cy1rZXlzZXQtdGVzdC1iMB4XDTE0MDkxMTAwNDQ0MVoXDTQyMDEyNzAw
+NDQ0MVowHDEaMBgGA1UEAwwRY3RzLWtleXNldC10ZXN0LWIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCh4VmoypNtmKjMVNcyRe1IolHOfao4NmC9VcAD
+ApOLnTFhxs9wdN8rG2J/z6rs4Kn/nQlgMffZuDrCRS6efn50RoeTFljx3u7Djq1C
+2Xl00aL7pxzgx7NUsJLqeSo0O6wCB2+AtToWXpIaLTYpOnW+S3oLAs73vtgk/uS3
+2i4NFMbsBImKrc7JFGg6pgeEP2CmxtSrjD7VtcZ+65m6MDV1fKi9e2+sdQY50UgQ
+Fg5VgZ8JzCHeVc+aM0kyUe0pCS6urz8sftrUHmhyhcIazJHxgd2VZ+upEB/OA4HU
+oKc02ZaqyRT0s5yLe5Cf0gN4wQWYB3wWoXxLBX7gu52T/FYZAgMBAAGjUDBOMB0G
+A1UdDgQWBBTM1NnUfcwYiJ3Loy3jfmVwyI+BCTAfBgNVHSMEGDAWgBTM1NnUfcwY
+iJ3Loy3jfmVwyI+BCTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBh
+lRz5yaYpswtWDVPWKnJ5btyXsLIQtWeFkxGxRXSrsFLvCMq7CxjO9VF1l+q+6UmK
+B6BEcrjm7uhmjAXS/ygUGjY1FZNVHwydJ/60Nn/Q0jx242A1+dBtLSS0FnEg+r3P
+3fvocr0SemAt6FY61gJ+4Zr8IQZc8C1qr5e/eDiMPBKectGzH1cniWqq1/5nc/vC
+hTTokZSnXh7PZLzF+iKOceO+nvx4yzm7q/YOM0tAP8PknrWcNAeIPRDvsERwp9fR
+IRTnyd3Ds4H/xD6OioMO+lk45H7vDU3TmoAYbDtCNvgS9Sd1lB/h3XPVH29QqwkW
+4xScMf6rzziGC+RdETpU
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.pk8 b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.pk8
new file mode 100644
index 0000000..303f1ad
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.x509.pem b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.x509.pem
new file mode 100644
index 0000000..324f218
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIJAI8ugk5OF4ENMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMMEWN0cy1rZXlzZXQtdGVzdC1jMB4XDTE0MDkxMTAwNDQyMloXDTQyMDEyNzAw
+NDQyMlowHDEaMBgGA1UEAwwRY3RzLWtleXNldC10ZXN0LWMwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCvAgn+n3NnqkZ7uHWUElQsTmVthsLeaHkbjc6w
+n4HQJ5s3grMQrJWD7CaS4ZK8bbFdSnUGVuKlKOdMnltS3aIG7AHzUu+6aD0Y58Kl
+MEa18ThriKC1+jt7ZTwhtHMRhuFpmUESYLUENS91MV0xEZk+6FRwyTCK3hGkeQvq
+u22459p6gnCyASNsQvLOByb7Vnj0N6f8maZc0YzDX9AyJsEUa8aSG7aseD9JiIqm
+6lyVTgUh4Atw5Kc+Sutjou5IBMcOdi+68rdWG7QQEogP6sC/mPoE2+e7blIB/caB
+Ls8u7JWWGITmneFN69efmD/u2MmVdrQWxsyWcV/ndbI/2lFbAgMBAAGjUDBOMB0G
+A1UdDgQWBBQbgTfHOXShdjNob5N5in97g4W97TAfBgNVHSMEGDAWgBQbgTfHOXSh
+djNob5N5in97g4W97TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAn
+bOLKe3ixKqLkMsgocHWvkeUqFahYbiPN11JKTFrgQVYwfpUnXN/YQfLSjAWDyzZ3
+niXYSai2COtIqEpQICp4JceEfoZUCbHdATA7Wxvfr+yrv+HG7F8wzhyxa5Pbcu9y
+b3ekjKT1rF4SxK0Ixt9vv34VSO98qAzx2Yq7VQwOKLJG6MDxqXX/tiTxpK7sEfAb
+pgJjHVZkX1rgQtv2e0RLFgcRyiYpxFbFzBLi/1b6EzK2kkg9FNLm+44CYkYFj7WC
+bjlY7o94DQ/CuEDVHCu/DSTp4QjvHC2ewTeXu05XkzSWKKLdsqecnZxXNueuqT5F
+Uhj9Fi4KQqT7tKqd+CuK
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/DocumentsTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/DocumentsTest.java
new file mode 100644
index 0000000..fbde558
--- /dev/null
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/DocumentsTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2014 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.appsecurity;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+public class DocumentsTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+ private static final String PROVIDER_PKG = "com.android.cts.documentprovider";
+ private static final String PROVIDER_APK = "CtsDocumentProvider.apk";
+
+ private static final String CLIENT_PKG = "com.android.cts.documentclient";
+ private static final String CLIENT_APK = "CtsDocumentClient.apk";
+
+ private IAbi mAbi;
+ private CtsBuildHelper mCtsBuild;
+
+ @Override
+ public void setAbi(IAbi abi) {
+ mAbi = abi;
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ assertNotNull(mAbi);
+ assertNotNull(mCtsBuild);
+
+ getDevice().uninstallPackage(PROVIDER_PKG);
+ getDevice().uninstallPackage(CLIENT_PKG);
+
+ assertNull(getDevice().installPackage(mCtsBuild.getTestApp(PROVIDER_APK), false));
+ assertNull(getDevice().installPackage(mCtsBuild.getTestApp(CLIENT_APK), false));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ getDevice().uninstallPackage(PROVIDER_PKG);
+ getDevice().uninstallPackage(CLIENT_PKG);
+ }
+
+ public void testOpenSimple() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenSimple");
+ }
+
+ public void testCreateNew() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateNew");
+ }
+
+ public void testCreateExisting() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateExisting");
+ }
+
+ public void testTree() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTree");
+ }
+
+ public void testGetContent() throws Exception {
+ runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testGetContent");
+ }
+
+ public void runDeviceTests(String packageName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+ }
+}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java
new file mode 100644
index 0000000..dae5ee7
--- /dev/null
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2014 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.cts.appsecurity;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Map;
+
+/**
+ * Tests for Keyset based features.
+ */
+public class KeySetHostTest extends DeviceTestCase implements IBuildReceiver {
+
+ private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+
+ /* package with device-side tests */
+ private static final String KEYSET_TEST_PKG = "com.android.cts.keysets.testapp";
+ private static final String KEYSET_TEST_APP_APK = "CtsKeySetTestApp.apk";
+
+ /* plain test apks with different signing and upgrade keysets */
+ private static final String KEYSET_PKG = "com.android.cts.keysets";
+ private static final String A_SIGNED_NO_UPGRADE =
+ "CtsKeySetSigningAUpgradeNone.apk";
+ private static final String A_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningAUpgradeA.apk";
+ private static final String A_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningAUpgradeB.apk";
+ private static final String A_SIGNED_A_OR_B_UPGRADE =
+ "CtsKeySetSigningAUpgradeAOrB.apk";
+ private static final String B_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningBUpgradeA.apk";
+ private static final String B_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningBUpgradeB.apk";
+ private static final String A_AND_B_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningAAndBUpgradeA.apk";
+ private static final String A_AND_B_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningAAndBUpgradeB.apk";
+ private static final String A_AND_C_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningAAndCUpgradeB.apk";
+
+ /* package which defines the KEYSET_PERM_NAME signature permission */
+ private static final String KEYSET_PERM_DEF_PKG =
+ "com.android.cts.keysets_permdef";
+
+ /* The apks defining and using the permission have both A and B as upgrade keys */
+ private static final String PERM_DEF_A_SIGNED =
+ "CtsKeySetPermDefSigningA.apk";
+ private static final String PERM_DEF_B_SIGNED =
+ "CtsKeySetPermDefSigningB.apk";
+ private static final String PERM_USE_A_SIGNED =
+ "CtsKeySetPermUseSigningA.apk";
+ private static final String PERM_USE_B_SIGNED =
+ "CtsKeySetPermUseSigningB.apk";
+
+ private static final String PERM_TEST_CLASS =
+ "com.android.cts.keysets.KeySetPermissionsTest";
+
+ private static final String LOG_TAG = "AppsecurityHostTests";
+
+ private File getTestAppFile(String fileName) throws FileNotFoundException {
+ return mCtsBuild.getTestApp(fileName);
+ }
+
+ /**
+ * Helper method that checks that all tests in given result passed, and attempts to generate
+ * a meaningful error message if they failed.
+ *
+ * @param result
+ */
+ private void assertDeviceTestsPass(TestRunResult result) {
+ assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
+ result.getName(), result.getRunFailureMessage()), result.isRunFailure());
+
+ if (result.hasFailedTests()) {
+
+ /* build a meaningful error message */
+ StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+ for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ result.getTestResults().entrySet()) {
+ if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ fail(errorBuilder.toString());
+ }
+ }
+
+ /**
+ * Helper method that checks that all tests in given result passed, and attempts to generate
+ * a meaningful error message if they failed.
+ *
+ * @param result
+ */
+ private void assertDeviceTestsFail(String msg, TestRunResult result) {
+ assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
+ result.getName(), result.getRunFailureMessage()), result.isRunFailure());
+
+ if (!result.hasFailedTests()) {
+ fail(msg);
+ }
+ }
+
+ /**
+ * Helper method that will run the specified packages tests on device.
+ *
+ * @param pkgName Android application package for tests
+ * @return <code>true</code> if all tests passed.
+ * @throws DeviceNotAvailableException if connection to device was lost.
+ */
+ private boolean runDeviceTests(String pkgName) throws DeviceNotAvailableException {
+ return runDeviceTests(pkgName, null, null);
+ }
+
+ /**
+ * Helper method that will run the specified packages tests on device.
+ *
+ * @param pkgName Android application package for tests
+ * @return <code>true</code> if all tests passed.
+ * @throws DeviceNotAvailableException if connection to device was lost.
+ */
+ private boolean runDeviceTests(String pkgName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ TestRunResult runResult = doRunTests(pkgName, testClassName, testMethodName);
+ return !runResult.hasFailedTests();
+ }
+
+ /**
+ * Helper method to run tests and return the listener that collected the results.
+ *
+ * @param pkgName Android application package for tests
+ * @return the {@link TestRunResult}
+ * @throws DeviceNotAvailableException if connection to device was lost.
+ */
+ private TestRunResult doRunTests(String pkgName, String testClassName,
+ String testMethodName) throws DeviceNotAvailableException {
+
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName,
+ RUNNER, getDevice().getIDevice());
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ }
+ CollectingTestListener listener = new CollectingTestListener();
+ getDevice().runInstrumentationTests(testRunner, listener);
+ return listener.getCurrentRunResults();
+ }
+
+ /**
+ * Helper method which installs a package and an upgrade to it.
+ *
+ * @param pkgName - package name of apk.
+ * @param firstApk - first apk to install
+ * @param secondApk - apk to which we attempt to upgrade
+ * @param expectedResult - null if successful, otherwise expected error.
+ */
+ private String testPackageUpgrade(String pkgName, String firstApk,
+ String secondApk) throws Exception {
+ String installResult;
+ try {
+
+ /* cleanup test apps that might be installed from previous partial test run */
+ mDevice.uninstallPackage(pkgName);
+
+ installResult = mDevice.installPackage(getTestAppFile(firstApk),
+ false);
+ /* we should always succeed on first-install */
+ assertNull(String.format("failed to install %s, Reason: %s", pkgName,
+ installResult), installResult);
+
+ /* attempt to install upgrade */
+ installResult = mDevice.installPackage(getTestAppFile(secondApk),
+ true);
+ } finally {
+ mDevice.uninstallPackage(pkgName);
+ }
+ return installResult;
+ }
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ private CtsBuildHelper mCtsBuild;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+ assertNotNull(mCtsBuild);
+ }
+
+ /**
+ * Tests for KeySet based key rotation
+ */
+
+ /*
+ * Check if an apk which does not specify an upgrade-key-set may be upgraded
+ * to an apk which does.
+ */
+ public void testNoKSToUpgradeKS() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_NO_UPGRADE, A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from no specified upgrade-key-set"
+ + "to version with specified upgrade-key-set, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk which does specify an upgrade-key-set may be upgraded
+ * to an apk which does not.
+ */
+ public void testUpgradeKSToNoKS() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_NO_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from specified upgrade-key-set"
+ + "to version without specified upgrade-key-set, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by a key other than the upgrade keyset can update
+ * an app
+ */
+ public void testUpgradeKSWithWrongKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, B_SIGNED_A_UPGRADE);
+ assertNotNull("upgrade to improperly signed app succeeded!", installResult);
+ }
+
+ /*
+ * Check if an apk signed by its signing key, which is not an upgrade key,
+ * can upgrade an app.
+ */
+ public void testUpgradeKSWithWrongSigningKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, A_SIGNED_B_UPGRADE);
+ assertNotNull("upgrade to improperly signed app succeeded!",
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by its upgrade key, which is not its signing key,
+ * can upgrade an app.
+ */
+ public void testUpgradeKSWithUpgradeKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, B_SIGNED_B_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by its upgrade key, which is its signing key, can
+ * upgrade an app.
+ */
+ public void testUpgradeKSWithSigningUpgradeKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by multiple keys, one of which is its upgrade key,
+ * can upgrade an app.
+ */
+ public void testMultipleUpgradeKSWithUpgradeKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE,
+ A_AND_B_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by multiple keys, its signing keys,
+ * but none of which is an upgrade key, can upgrade an app.
+ */
+ public void testMultipleUpgradeKSWithSigningKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_AND_C_SIGNED_B_UPGRADE,
+ A_AND_C_SIGNED_B_UPGRADE);
+ assertNotNull("upgrade to improperly signed app succeeded!", installResult);
+ }
+
+ /*
+ * Check if an apk which defines multiple (two) upgrade keysets is
+ * upgrade-able by either.
+ */
+ public void testUpgradeKSWithMultipleUpgradeKeySetsFirstKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
+ A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to one signed by first upgrade keyset key-a, Reason: %s", installResult),
+ installResult);
+ installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
+ B_SIGNED_B_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to one signed by second upgrade keyset key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /**
+ * Helper method which installs a package defining a permission and a package
+ * using the permission, and then rotates the signing keys for one of them.
+ * A device-side test is then used to ascertain whether or not the permission
+ * was appropriately gained or lost.
+ *
+ * @param permDefApk - apk to install which defines the sig-permissoin
+ * @param permUseApk - apk to install which declares it uses the permission
+ * @param upgradeApk - apk to install which upgrades one of the first two
+ * @param hasPermBeforeUpgrade - whether we expect the consuming app to have
+ * the permission before the upgrade takes place.
+ * @param hasPermAfterUpgrade - whether we expect the consuming app to have
+ * the permission after the upgrade takes place.
+ */
+ private void testKeyRotationPerm(String permDefApk, String permUseApk,
+ String upgradeApk, boolean hasPermBeforeUpgrade,
+ boolean hasPermAfterUpgrade) throws Exception {
+ try {
+
+ /* cleanup test apps that might be installed from previous partial test run */
+ mDevice.uninstallPackage(KEYSET_PKG);
+ mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
+ mDevice.uninstallPackage(KEYSET_TEST_PKG);
+
+ /* install PERM_DEF, KEYSET_APP and KEYSET_TEST_APP */
+ String installResult = mDevice.installPackage(
+ getTestAppFile(permDefApk), false);
+ assertNull(String.format("failed to install keyset perm-def app, Reason: %s",
+ installResult), installResult);
+ installResult = getDevice().installPackage(
+ getTestAppFile(permUseApk), false);
+ assertNull(String.format("failed to install keyset test app. Reason: %s",
+ installResult), installResult);
+ installResult = getDevice().installPackage(
+ getTestAppFile(KEYSET_TEST_APP_APK), false);
+ assertNull(String.format("failed to install keyset test app. Reason: %s",
+ installResult), installResult);
+
+ /* verify package does have perm */
+ TestRunResult result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
+ "testHasPerm");
+ if (hasPermBeforeUpgrade) {
+ assertDeviceTestsPass(result);
+ } else {
+ assertDeviceTestsFail(" has permission permission it should not have.", result);
+ }
+
+ /* rotate keys */
+ installResult = mDevice.installPackage(getTestAppFile(upgradeApk),
+ true);
+ result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
+ "testHasPerm");
+ if (hasPermAfterUpgrade) {
+ assertDeviceTestsPass(result);
+ } else {
+ assertDeviceTestsFail(KEYSET_PKG + " has permission it should not have.", result);
+ }
+ } finally {
+ mDevice.uninstallPackage(KEYSET_PKG);
+ mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
+ mDevice.uninstallPackage(KEYSET_TEST_PKG);
+ }
+ }
+
+ /*
+ * Check if an apk gains signature-level permission after changing to a new
+ * signature, for which a permission should be granted.
+ */
+ public void testUpgradeSigPermGained() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_USE_A_SIGNED,
+ false, true);
+ }
+
+ /*
+ * Check if an apk loses signature-level permission after changing to a new
+ * signature, from one for which a permission was previously granted.
+ */
+ public void testUpgradeSigPermLost() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_USE_B_SIGNED,
+ true, false);
+ }
+
+ /*
+ * Check if an apk gains signature-level permission after the app defining
+ * it rotates to the same signature.
+ */
+ public void testUpgradeDefinerSigPermGained() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_DEF_B_SIGNED,
+ false, true);
+ }
+
+ /*
+ * Check if an apk loses signature-level permission after the app defining
+ * it rotates to a different signature.
+ */
+ public void testUpgradeDefinerSigPermLost() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_DEF_B_SIGNED,
+ true, false);
+ }
+}
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
index b9bc768..264c0b1 100644
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
@@ -18,15 +18,9 @@
import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.cts.util.AbiUtils;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
-import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
@@ -37,7 +31,6 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-import java.util.Map;
/**
* Tests that verify installing of various split APKs from host side.
@@ -355,43 +348,8 @@
}
}
- public void runDeviceTests(String packageName) throws DeviceNotAvailableException {
- runDeviceTests(packageName, null, null);
- }
-
public void runDeviceTests(String packageName, String testClassName, String testMethodName)
throws DeviceNotAvailableException {
- if (testClassName != null && testClassName.startsWith(".")) {
- testClassName = packageName + testClassName;
- }
-
- RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName,
- "android.support.test.runner.AndroidJUnitRunner", getDevice().getIDevice());
- if (testClassName != null && testMethodName != null) {
- testRunner.setMethodName(testClassName, testMethodName);
- }
-
- final CollectingTestListener listener = new CollectingTestListener();
- getDevice().runInstrumentationTests(testRunner, listener);
-
- final TestRunResult result = listener.getCurrentRunResults();
- if (result.isRunFailure()) {
- fail("Failed to successfully run device tests for " + result.getName() + ": "
- + result.getRunFailureMessage());
- }
-
- if (result.hasFailedTests()) {
- // build a meaningful error message
- StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
- result.getTestResults().entrySet()) {
- if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
- errorBuilder.append(resultEntry.getKey().toString());
- errorBuilder.append(":\n");
- errorBuilder.append(resultEntry.getValue().getStackTrace());
- }
- }
- fail(errorBuilder.toString());
- }
+ Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
}
}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/Utils.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/Utils.java
new file mode 100644
index 0000000..c58d6bf
--- /dev/null
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/Utils.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2014 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.appsecurity;
+
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+
+import java.util.Map;
+
+public class Utils {
+ public static void runDeviceTests(ITestDevice device, String packageName)
+ throws DeviceNotAvailableException {
+ runDeviceTests(device, packageName, null, null);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+ String testMethodName) throws DeviceNotAvailableException {
+ if (testClassName != null && testClassName.startsWith(".")) {
+ testClassName = packageName + testClassName;
+ }
+
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName,
+ "android.support.test.runner.AndroidJUnitRunner", device.getIDevice());
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ }
+
+ final CollectingTestListener listener = new CollectingTestListener();
+ device.runInstrumentationTests(testRunner, listener);
+
+ final TestRunResult result = listener.getCurrentRunResults();
+ if (result.isRunFailure()) {
+ throw new AssertionError("Failed to successfully run device tests for "
+ + result.getName() + ": " + result.getRunFailureMessage());
+ }
+
+ if (result.hasFailedTests()) {
+ // build a meaningful error message
+ StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+ for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ result.getTestResults().entrySet()) {
+ if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ throw new AssertionError(errorBuilder.toString());
+ }
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk b/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk
new file mode 100644
index 0000000..910e3cd
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2014 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 := android-support-test ctsdeviceutil ctstestrunner ub-uiautomator
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsDocumentClient
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml
new file mode 100644
index 0000000..0064e15
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.documentclient">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:name=".MyActivity" />
+ </application>
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.documentclient" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
new file mode 100644
index 0000000..83187c7
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2014 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.documentclient;
+
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsProvider;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+import android.test.InstrumentationTestCase;
+import android.test.MoreAsserts;
+
+import com.android.cts.documentclient.MyActivity.Result;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Tests for {@link DocumentsProvider} and interaction with platform intents
+ * like {@link Intent#ACTION_OPEN_DOCUMENT}.
+ */
+public class DocumentsClientTest extends InstrumentationTestCase {
+ private UiDevice mDevice;
+ private MyActivity mActivity;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
+ MyActivity.class, null);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ mActivity.finish();
+ }
+
+ public void testOpenSimple() throws Exception {
+ if (!supportedHardware()) return;
+
+ try {
+ // Opening without permission should fail
+ readFully(Uri.parse("content://com.android.cts.documentprovider/document/doc:file1"));
+ fail("Able to read data before opened!");
+ } catch (SecurityException expected) {
+ }
+
+ final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ mActivity.startActivityForResult(intent, 42);
+
+ // Ensure that we see both of our roots
+ assertTrue("CtsLocal root", new UiObject(new UiSelector().text("CtsLocal")).exists());
+ assertTrue("CtsCreate root", new UiObject(new UiSelector().text("CtsCreate")).exists());
+ assertFalse("CtsGetContent", new UiObject(new UiSelector().text("CtsGetContent")).exists());
+
+ // Pick a specific file from our test provider
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().text("CtsLocal")).click();
+
+ // make sure drawer is expanded?
+
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().text("FILE1")).click();
+
+ final Result result = mActivity.getResult();
+ final Uri uri = result.data.getData();
+
+ // We should now have permission to read/write
+ MoreAsserts.assertEquals("fileone".getBytes(), readFully(uri));
+
+ writeFully(uri, "replaced!".getBytes());
+ SystemClock.sleep(500);
+ MoreAsserts.assertEquals("replaced!".getBytes(), readFully(uri));
+ }
+
+ public void testCreateNew() throws Exception {
+ if (!supportedHardware()) return;
+
+ final String DISPLAY_NAME = "My New Awesome Document Title";
+ final String MIME_TYPE = "image/png";
+
+ final Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.putExtra(Intent.EXTRA_TITLE, DISPLAY_NAME);
+ intent.setType(MIME_TYPE);
+ mActivity.startActivityForResult(intent, 42);
+
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().text("CtsCreate")).click();
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().resourceId("com.android.documentsui:id/container_save")
+ .childSelector(new UiSelector().resourceId("android:id/button1"))).click();
+
+ final Result result = mActivity.getResult();
+ final Uri uri = result.data.getData();
+
+ writeFully(uri, "meow!".getBytes());
+
+ assertEquals(DISPLAY_NAME, getColumn(uri, Document.COLUMN_DISPLAY_NAME));
+ assertEquals(MIME_TYPE, getColumn(uri, Document.COLUMN_MIME_TYPE));
+ }
+
+ public void testCreateExisting() throws Exception {
+ if (!supportedHardware()) return;
+
+ final Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.putExtra(Intent.EXTRA_TITLE, "NEVERUSED");
+ intent.setType("mime2/file2");
+ mActivity.startActivityForResult(intent, 42);
+
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().text("CtsCreate")).click();
+
+ // Pick file2, which should be selected since MIME matches, then try
+ // picking a non-matching MIME, which should leave file2 selected.
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().text("FILE2")).click();
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().text("FILE1")).click();
+
+ new UiObject(new UiSelector().resourceId("com.android.documentsui:id/container_save")
+ .childSelector(new UiSelector().resourceId("android:id/button1"))).click();
+
+ final Result result = mActivity.getResult();
+ final Uri uri = result.data.getData();
+
+ MoreAsserts.assertEquals("filetwo".getBytes(), readFully(uri));
+ }
+
+ public void testTree() throws Exception {
+ if (!supportedHardware()) return;
+
+ final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
+ mActivity.startActivityForResult(intent, 42);
+
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().text("CtsCreate")).click();
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().text("DIR2")).click();
+ mDevice.waitForIdle();
+ new UiObject(new UiSelector().resourceId("com.android.documentsui:id/container_save")
+ .childSelector(new UiSelector().resourceId("android:id/button1"))).click();
+
+ final Result result = mActivity.getResult();
+ final Uri uri = result.data.getData();
+
+ // We should have selected DIR2
+ Uri doc = DocumentsContract.buildDocumentUriUsingTree(uri,
+ DocumentsContract.getTreeDocumentId(uri));
+ Uri children = DocumentsContract.buildChildDocumentsUriUsingTree(uri,
+ DocumentsContract.getTreeDocumentId(uri));
+
+ assertEquals("DIR2", getColumn(doc, Document.COLUMN_DISPLAY_NAME));
+
+ // Look around and make sure we can see children
+ final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
+ Cursor cursor = resolver.query(children, new String[] {
+ Document.COLUMN_DISPLAY_NAME }, null, null, null);
+ try {
+ assertEquals(1, cursor.getCount());
+ assertTrue(cursor.moveToFirst());
+ assertEquals("FILE4", cursor.getString(0));
+ } finally {
+ cursor.close();
+ }
+
+ // Create some documents
+ Uri pic = DocumentsContract.createDocument(resolver, doc, "image/png", "pic.png");
+ Uri dir = DocumentsContract.createDocument(resolver, doc, Document.MIME_TYPE_DIR, "my dir");
+ Uri dirPic = DocumentsContract.createDocument(resolver, dir, "image/png", "pic2.png");
+
+ writeFully(pic, "pic".getBytes());
+ writeFully(dirPic, "dirPic".getBytes());
+
+ // Read then delete existing doc
+ final Uri file4 = DocumentsContract.buildDocumentUriUsingTree(uri, "doc:file4");
+ MoreAsserts.assertEquals("filefour".getBytes(), readFully(file4));
+ assertTrue("delete", DocumentsContract.deleteDocument(resolver, file4));
+ try {
+ MoreAsserts.assertEquals("filefour".getBytes(), readFully(file4));
+ fail("Expected file to be gone");
+ } catch (FileNotFoundException expected) {
+ }
+
+ // And rename something
+ dirPic = DocumentsContract.renameDocument(resolver, dirPic, "wow");
+ assertNotNull("rename", dirPic);
+
+ // We should only see single child
+ assertEquals("wow", getColumn(dirPic, Document.COLUMN_DISPLAY_NAME));
+ MoreAsserts.assertEquals("dirPic".getBytes(), readFully(dirPic));
+
+ try {
+ // Make sure we can't see files outside selected dir
+ getColumn(DocumentsContract.buildDocumentUriUsingTree(uri, "doc:file1"),
+ Document.COLUMN_DISPLAY_NAME);
+ fail("Somehow read document outside tree!");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ public void testGetContent() throws Exception {
+ if (!supportedHardware()) return;
+
+ final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ mActivity.startActivityForResult(intent, 42);
+
+ mDevice.waitForIdle();
+
+ // Look around, we should be able to see both DocumentsProviders and
+ // other GET_CONTENT sources.
+ assertTrue("CtsLocal root", new UiObject(new UiSelector().text("CtsLocal")).exists());
+ assertTrue("CtsCreate root", new UiObject(new UiSelector().text("CtsCreate")).exists());
+ assertTrue("CtsGetContent", new UiObject(new UiSelector().text("CtsGetContent")).exists());
+
+ new UiObject(new UiSelector().text("CtsGetContent")).click();
+ mDevice.waitForIdle();
+
+ final Result result = mActivity.getResult();
+ assertEquals("ReSuLt", result.data.getAction());
+ }
+
+ private String getColumn(Uri uri, String column) {
+ final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
+ final Cursor cursor = resolver.query(uri, new String[] { column }, null, null, null);
+ try {
+ assertTrue(cursor.moveToFirst());
+ return cursor.getString(0);
+ } finally {
+ cursor.close();
+ }
+ }
+
+ private byte[] readFully(Uri uri) throws IOException {
+ InputStream in = getInstrumentation().getContext().getContentResolver()
+ .openInputStream(uri);
+ try {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int count;
+ while ((count = in.read(buffer)) != -1) {
+ bytes.write(buffer, 0, count);
+ }
+ return bytes.toByteArray();
+ } finally {
+ in.close();
+ }
+ }
+
+ private void writeFully(Uri uri, byte[] data) throws IOException {
+ OutputStream out = getInstrumentation().getContext().getContentResolver()
+ .openOutputStream(uri);
+ try {
+ out.write(data);
+ } finally {
+ out.close();
+ }
+ }
+
+ private boolean supportedHardware() {
+ final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+ if (pm.hasSystemFeature("android.hardware.type.television")
+ || pm.hasSystemFeature("android.hardware.type.watch")) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/MyActivity.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/MyActivity.java
new file mode 100644
index 0000000..a6cb28d
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/MyActivity.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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.documentclient;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+
+public class MyActivity extends Activity {
+ private final SynchronousQueue<Result> mResult = new SynchronousQueue<>();
+
+ public static class Result {
+ public final int resultCode;
+ public final Intent data;
+
+ public Result(int resultCode, Intent data) {
+ this.resultCode = resultCode;
+ this.data = data;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ try {
+ mResult.offer(new Result(resultCode, data), 5, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Result getResult() {
+ try {
+ return mResult.take();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk
new file mode 100644
index 0000000..a886fb2
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2014 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 := android-support-test ctsdeviceutil ctstestrunner ub-uiautomator
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsDocumentProvider
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml
new file mode 100644
index 0000000..c0fc6cc
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.documentprovider">
+ <application>
+ <provider android:name=".MyDocumentsProvider"
+ android:authorities="com.android.cts.documentprovider"
+ android:exported="true"
+ android:grantUriPermissions="true"
+ android:permission="android.permission.MANAGE_DOCUMENTS">
+ <intent-filter>
+ <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
+ </intent-filter>
+ </provider>
+
+ <activity android:name=".GetContentActivity"
+ android:label="CtsGetContent">
+ <intent-filter>
+ <action android:name="android.intent.action.GET_CONTENT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.OPENABLE" />
+ <data android:mimeType="image/*" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/GetContentActivity.java b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/GetContentActivity.java
new file mode 100644
index 0000000..1aba526
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/GetContentActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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.documentprovider;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class GetContentActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setResult(Activity.RESULT_OK, new Intent("ReSuLt"));
+ finish();
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
new file mode 100644
index 0000000..fb8993c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2014 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.documentprovider;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.os.AsyncTask;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
+import android.provider.DocumentsProvider;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MyDocumentsProvider extends DocumentsProvider {
+ private static final String TAG = "TestDocumentsProvider";
+
+ private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
+ Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
+ Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES,
+ };
+
+ private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
+ Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
+ Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
+ };
+
+ private static String[] resolveRootProjection(String[] projection) {
+ return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
+ }
+
+ private static String[] resolveDocumentProjection(String[] projection) {
+ return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
+ }
+
+ @Override
+ public boolean onCreate() {
+ resetRoots();
+ return true;
+ }
+
+ @Override
+ public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
+
+ RowBuilder row = result.newRow();
+ row.add(Root.COLUMN_ROOT_ID, "local");
+ row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY);
+ row.add(Root.COLUMN_TITLE, "CtsLocal");
+ row.add(Root.COLUMN_SUMMARY, "CtsLocalSummary");
+ row.add(Root.COLUMN_DOCUMENT_ID, "doc:local");
+
+ row = result.newRow();
+ row.add(Root.COLUMN_ROOT_ID, "create");
+ row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD);
+ row.add(Root.COLUMN_TITLE, "CtsCreate");
+ row.add(Root.COLUMN_DOCUMENT_ID, "doc:create");
+
+ return result;
+ }
+
+ private Map<String, Doc> mDocs = new HashMap<>();
+
+ private Doc mLocalRoot;
+ private Doc mCreateRoot;
+
+ private Doc buildDoc(String docId, String displayName, String mimeType) {
+ final Doc doc = new Doc();
+ doc.docId = docId;
+ doc.displayName = displayName;
+ doc.mimeType = mimeType;
+ mDocs.put(doc.docId, doc);
+ return doc;
+ }
+
+ public void resetRoots() {
+ Log.d(TAG, "resetRoots()");
+
+ mDocs.clear();
+
+ mLocalRoot = buildDoc("doc:local", null, Document.MIME_TYPE_DIR);
+
+ mCreateRoot = buildDoc("doc:create", null, Document.MIME_TYPE_DIR);
+ mCreateRoot.flags = Document.FLAG_DIR_SUPPORTS_CREATE;
+
+ {
+ Doc file1 = buildDoc("doc:file1", "FILE1", "mime1/file1");
+ file1.contents = "fileone".getBytes();
+ file1.flags = Document.FLAG_SUPPORTS_WRITE;
+ mLocalRoot.children.add(file1);
+ mCreateRoot.children.add(file1);
+ }
+
+ {
+ Doc file2 = buildDoc("doc:file2", "FILE2", "mime2/file2");
+ file2.contents = "filetwo".getBytes();
+ file2.flags = Document.FLAG_SUPPORTS_WRITE;
+ mLocalRoot.children.add(file2);
+ mCreateRoot.children.add(file2);
+ }
+
+ Doc dir1 = buildDoc("doc:dir1", "DIR1", Document.MIME_TYPE_DIR);
+ mLocalRoot.children.add(dir1);
+
+ {
+ Doc file3 = buildDoc("doc:file3", "FILE3", "mime3/file3");
+ file3.contents = "filethree".getBytes();
+ file3.flags = Document.FLAG_SUPPORTS_WRITE;
+ dir1.children.add(file3);
+ }
+
+ Doc dir2 = buildDoc("doc:dir2", "DIR2", Document.MIME_TYPE_DIR);
+ mCreateRoot.children.add(dir2);
+
+ {
+ Doc file4 = buildDoc("doc:file4", "FILE4", "mime4/file4");
+ file4.contents = "filefour".getBytes();
+ file4.flags = Document.FLAG_SUPPORTS_WRITE;
+ dir2.children.add(file4);
+ }
+ }
+
+ private static class Doc {
+ public String docId;
+ public int flags;
+ public String displayName;
+ public long size;
+ public String mimeType;
+ public long lastModified;
+ public byte[] contents;
+ public List<Doc> children = new ArrayList<>();
+
+ public void include(MatrixCursor result) {
+ final RowBuilder row = result.newRow();
+ row.add(Document.COLUMN_DOCUMENT_ID, docId);
+ row.add(Document.COLUMN_DISPLAY_NAME, displayName);
+ row.add(Document.COLUMN_SIZE, size);
+ row.add(Document.COLUMN_MIME_TYPE, mimeType);
+ row.add(Document.COLUMN_FLAGS, flags);
+ row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
+ }
+ }
+
+ @Override
+ public boolean isChildDocument(String parentDocumentId, String documentId) {
+ for (Doc doc : mDocs.get(parentDocumentId).children) {
+ if (doc.docId.equals(documentId)) {
+ return true;
+ }
+ if (Document.MIME_TYPE_DIR.equals(doc.mimeType)) {
+ return isChildDocument(doc.docId, documentId);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String createDocument(String parentDocumentId, String mimeType, String displayName)
+ throws FileNotFoundException {
+ final String docId = "doc:" + System.currentTimeMillis();
+ final Doc doc = buildDoc(docId, displayName, mimeType);
+ doc.flags = Document.FLAG_SUPPORTS_WRITE | Document.FLAG_SUPPORTS_RENAME;
+ mDocs.get(parentDocumentId).children.add(doc);
+ return docId;
+ }
+
+ @Override
+ public String renameDocument(String documentId, String displayName)
+ throws FileNotFoundException {
+ mDocs.get(documentId).displayName = displayName;
+ return null;
+ }
+
+ @Override
+ public void deleteDocument(String documentId) throws FileNotFoundException {
+ mDocs.remove(documentId);
+ for (Doc doc : mDocs.values()) {
+ doc.children.remove(documentId);
+ }
+ }
+
+ @Override
+ public Cursor queryDocument(String documentId, String[] projection)
+ throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
+ mDocs.get(documentId).include(result);
+ return result;
+ }
+
+ @Override
+ public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
+ String sortOrder) throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
+ for (Doc doc : mDocs.get(parentDocumentId).children) {
+ doc.include(result);
+ }
+ return result;
+ }
+
+ @Override
+ public ParcelFileDescriptor openDocument(String documentId, String mode,
+ CancellationSignal signal) throws FileNotFoundException {
+ final Doc doc = mDocs.get(documentId);
+ if (doc == null) {
+ throw new FileNotFoundException();
+ }
+ final ParcelFileDescriptor[] pipe;
+ try {
+ pipe = ParcelFileDescriptor.createPipe();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ if (mode.contains("w")) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ final InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(
+ pipe[0]);
+ doc.contents = readFullyNoClose(is);
+ is.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to stream", e);
+ }
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return pipe[1];
+ } else {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ final OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(
+ pipe[1]);
+ os.write(doc.contents);
+ os.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to stream", e);
+ }
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return pipe[0];
+ }
+ }
+
+ private static byte[] readFullyNoClose(InputStream in) throws IOException {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int count;
+ while ((count = in.read(buffer)) != -1) {
+ bytes.write(buffer, 0, count);
+ }
+ return bytes.toByteArray();
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/keysets/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/Android.mk
new file mode 100644
index 0000000..935fa95
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/Android.mk
@@ -0,0 +1,21 @@
+# Copyright (C) 2014 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)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk
new file mode 100644
index 0000000..eb71540
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2014 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermDefSigningA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermDefSigningB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/permDef/AndroidManifest.xml
new file mode 100644
index 0000000..7b84f6a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.keysets_permdef">
+ <application android:hasCode="false">
+ </application>
+ <permission android:description="@string/keysets_perm_desc"
+ android:label="@string/keysets_perm_label"
+ android:name="com.android.cts.keysets_permdef.keysets_perm"
+ android:protectionLevel="signature" />
+ <key-sets>
+ <key-set android:name="A" >
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ </key-set>
+ <key-set android:name="B" >
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="A"/>
+ <upgrade-key-set android:name="B"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/keysets/permDef/res/values/strings.xml
new file mode 100644
index 0000000..4e5e870
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keysets_perm_desc">keysets_perm_description</string>
+ <string name="keysets_perm_label">keysets_perm_label</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk
new file mode 100644
index 0000000..000b12a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2014 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermUseSigningA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermUseSigningB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/permUse/AndroidManifest.xml
new file mode 100644
index 0000000..40ca1cb
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.keysets">
+ <application android:hasCode="false">
+ </application>
+ <uses-permission android:name="com.android.cts.keysets_permdef.keysets_perm" />
+ <key-sets>
+ <key-set android:name="A">
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ </key-set>
+ <key-set android:name="B">
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="A"/>
+ <upgrade-key-set android:name="B"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/keysets/permUse/res/values/strings.xml
new file mode 100644
index 0000000..4e5e870
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keysets_perm_desc">keysets_perm_description</string>
+ <string name="keysets_perm_label">keysets_perm_label</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk
new file mode 100644
index 0000000..ed6db69
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk
@@ -0,0 +1,26 @@
+# Copyright (C) 2014 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_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetTestApp
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/testApp/AndroidManifest.xml
new file mode 100644
index 0000000..38edf5f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.keysets.testapp">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:targetPackage="com.android.cts.keysets.testapp"
+ android:name="android.support.test.runner.AndroidJUnitRunner" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/src/com/android/cts/keysets/KeySetPermissionsTest.java b/hostsidetests/appsecurity/test-apps/keysets/testApp/src/com/android/cts/keysets/KeySetPermissionsTest.java
new file mode 100644
index 0000000..467a212
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/src/com/android/cts/keysets/KeySetPermissionsTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.keysets;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.util.Log;
+import android.test.AndroidTestCase;
+
+import java.lang.Override;
+
+/**
+ * KeySets device-side tests involving permissions
+ */
+public class KeySetPermissionsTest extends AndroidTestCase {
+
+ private static final String KEYSET_APP_PKG = "com.android.cts.keysets";
+ private static final String KEYSET_PERM_DEF_PKG = "com.android.cts.keysets_permdef";
+ private static final String KEYSET_PERM_NAME = "com.android.cts.keysets_permdef.keysets_perm";
+
+ public void testHasPerm() throws Exception {
+ PackageManager pm = getContext().getPackageManager();
+ assertTrue(KEYSET_PERM_NAME + " not granted to " + KEYSET_APP_PKG,
+ pm.checkPermission(KEYSET_PERM_NAME, KEYSET_APP_PKG) == PackageManager.PERMISSION_GRANTED);
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk
new file mode 100644
index 0000000..6220790
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk
@@ -0,0 +1,53 @@
+# Copyright (C) 2014 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)
+
+#apks signed by cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed by cts-keyset-test-b
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningBUpgradeA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed by cts-keyset-test-a and cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAAndBUpgradeA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_ADDITIONAL_CERTIFICATES := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uA/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uA/AndroidManifest.xml
new file mode 100644
index 0000000..8813c37
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uA/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.keysets">
+ <application android:hasCode="false">
+ </application>
+ <key-sets>
+ <key-set android:name="A" >
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="A"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk
new file mode 100644
index 0000000..534dba3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2014 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeAAndB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAB/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uAB/AndroidManifest.xml
new file mode 100644
index 0000000..65f78e3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAB/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.keysets">
+ <application android:hasCode="false">
+ </application>
+ <key-sets>
+ <key-set android:name="AB" >
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="AB"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk
new file mode 100644
index 0000000..75729e0
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2014 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeAOrB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAuB/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uAuB/AndroidManifest.xml
new file mode 100644
index 0000000..546c5fe
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAuB/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.keysets">
+ <application android:hasCode="false">
+ </application>
+ <key-sets>
+ <key-set android:name="A" >
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ </key-set>
+ <key-set android:name="B" >
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="A"/>
+ <upgrade-key-set android:name="B"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk
new file mode 100644
index 0000000..121c342
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk
@@ -0,0 +1,55 @@
+# Copyright (C) 2014 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningBUpgradeB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed by cts-keyset-test-a and cts-keyset-test-c
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAAndCUpgradeB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_ADDITIONAL_CERTIFICATES := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uB/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uB/AndroidManifest.xml
new file mode 100644
index 0000000..9c837bc
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uB/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.keysets">
+ <application android:hasCode="false">
+ </application>
+ <key-sets>
+ <key-set android:name="B" >
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="B"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk
new file mode 100644
index 0000000..a8746ec
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2014 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeNone
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uNone/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uNone/AndroidManifest.xml
new file mode 100644
index 0000000..55304f4
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uNone/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.keysets">
+ <application android:hasCode="false">
+ </application>
+</manifest>
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 40a66d2..8adf345 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -143,7 +143,7 @@
{
description: "This test failed on devices that use effect off loading. In addition it uses hidden apis",
names: [
- "android.meida.cts.AudioEffectTest#test1_1ConstructorFromUuid"
+ "android.media.cts.AudioEffectTest#test1_1ConstructorFromUuid"
],
bug: 17605875
},
@@ -319,7 +319,7 @@
{
description: "This test failed on hw decoder that doesn't output frame with the configured format.",
names: [
- "android.meida.cts.ImageReaderDecoderTest#testHwAVCDecode360pForFlexibleYuv"
+ "android.media.cts.ImageReaderDecoderTest#testHwAVCDecode360pForFlexibleYuv"
],
bug: 17144778
}
diff --git a/tests/tests/graphics/res/drawable/vector_icon_delete.xml b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
index 8d9c21c..7b8f2aa 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_delete.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
@@ -24,6 +24,6 @@
<path
android:fillColor="#FF000000"
- android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0-0.896 2.0-2.0l0.0-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
+ android:pathData="M6.0,19.0c0.0,1.104 896e-3,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0-896e-3 2.0-2.0l0.0-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_heart.xml b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
index ff55fe5..ad991c9 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_heart.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
@@ -24,6 +24,6 @@
<path
android:fillColor="#FF000000"
- android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
+ android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
</vector>
\ No newline at end of file
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
index a4d4157..d8b8e51 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
@@ -45,8 +45,8 @@
private static final String TAG = "SensorTest";
// Test only SDK defined sensors. Any sensors with type > 100 are ignored.
private static final int MAX_OFFICIAL_ANDROID_SENSOR_TYPE = 100;
- private static final long TIMEOUT_TOLERANCE_US = TimeUnit.SECONDS.toMicros(10);
-
+ private static final long TIMEOUT_TOLERANCE_US = TimeUnit.SECONDS.toMicros(5);
+ private static final double MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE = 0.9;
private PowerManager.WakeLock mWakeLock;
@Override
@@ -272,13 +272,17 @@
final long elapsedRealtimeNs = SystemClock.elapsedRealtimeNanos();
- if (elapsedRealtimeNs - currTimeStampNs > SYNC_TOLERANCE + mEventReportLatencyNs) {
+ if (elapsedRealtimeNs <= currTimeStampNs) {
+ Log.w(TAG, "Timestamps into the future curr elapsedRealTimeNs=" + elapsedRealtimeNs
+ + " current sensor ts_ns=" + currTimeStampNs);
+ ++numErrors;
+ } else if (elapsedRealtimeNs-currTimeStampNs > SYNC_TOLERANCE + mEventReportLatencyNs) {
Log.w(TAG, "Timestamp sync error elapsedRealTimeNs=" + elapsedRealtimeNs +
" curr_ts_ns=" + currTimeStampNs +
" diff_ns=" + (elapsedRealtimeNs - currTimeStampNs) +
" SYNC_TOLERANCE_NS=" + SYNC_TOLERANCE +
" eventReportLatencyNs=" + mEventReportLatencyNs);
- numErrors++;
+ ++numErrors;
}
mPrevTimeStampNs = currTimeStampNs;
}
@@ -302,8 +306,10 @@
// elapsedRealTimeNano.
@TimeoutReq(minutes=60)
public void testSensorTimeStamps() throws Exception {
+ final int numEvents = 2000;
try {
mWakeLock.acquire();
+ int numErrors = 0;
for (Sensor sensor : mSensorList) {
// Skip OEM defined sensors and non continuous sensors.
if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
@@ -315,35 +321,45 @@
long maxBatchReportLatencyNs = 10000000000L; // 10 secs
if (iterations % 2 == 0) maxBatchReportLatencyNs = 0;
- final long samplingPeriodNs = 20000000;
- // If there is a FIFO and a wake-lock is held, events will be reported when the
- // batch timeout expires or when the FIFO is full which ever occurs earlier.
+ final long samplingPeriodNs = (long)(TimeUnit.MICROSECONDS.toNanos(
+ sensor.getMinDelay())/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE);
+ // If there is a FIFO and a wake-lock is held, events will be reported when
+ // the batch timeout expires or when the FIFO is full which ever occurs
+ // earlier.
final long eventReportLatencyNs = Math.min(maxBatchReportLatencyNs,
sensor.getFifoMaxEventCount() * samplingPeriodNs);
- final CountDownLatch eventReceivedLatch = new CountDownLatch(2000);
+ final CountDownLatch eventsRemaining = new CountDownLatch(numEvents);
SensorEventTimeStampListener listener = new SensorEventTimeStampListener(
- eventReportLatencyNs, eventReceivedLatch);
+ eventReportLatencyNs, eventsRemaining);
Log.i(TAG, "Running timeStamp test on " + sensor.getName());
boolean result = mSensorManager.registerListener(listener, sensor,
- SensorManager.SENSOR_DELAY_GAME, (int)maxBatchReportLatencyNs/1000);
+ SensorManager.SENSOR_DELAY_FASTEST,
+ (int)maxBatchReportLatencyNs/1000);
assertTrue("Sensor registerListener failed ", result);
- // Wait for 300 seconds.
- boolean countZero = eventReceivedLatch.await(300, TimeUnit.SECONDS);
- if (!countZero) {
- fail("Timed out waiting for events from " + sensor.getName());
+ long timeToWaitUs = samplingPeriodNs/1000 + eventReportLatencyNs/1000 +
+ TIMEOUT_TOLERANCE_US;
+ long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs,
+ (int)(eventReportLatencyNs/1000), eventsRemaining);
+
+ mSensorManager.unregisterListener(listener);
+ if (eventsRemaining.getCount() > 0) {
+ failTimedOut(sensor.getName(), (double) totalTimeWaitedUs/1000,
+ numEvents, (double) sensor.getMinDelay()/1000,
+ eventsRemaining.getCount(),
+ numEvents - eventsRemaining.getCount());
}
if (listener.getNumErrors() > 5) {
fail("Check logcat. Timestamp test failed. numErrors=" +
listener.getNumErrors() + " " + sensor.getName() +
" maxBatchReportLatencyNs=" + maxBatchReportLatencyNs +
- " samplingPeriodNs=" + samplingPeriodNs);
+ " samplingPeriodNs=" + sensor.getMinDelay());
+ numErrors += listener.getNumErrors();
} else {
Log.i(TAG, "TimeStamp test PASS'd on " + sensor.getName());
}
- mSensorManager.unregisterListener(listener);
}
}
} finally {
@@ -351,9 +367,18 @@
}
}
+ private void failTimedOut(String sensorName, double totalTimeWaitedMs, int numEvents,
+ double minDelayMs, long eventsRemaining, long eventsReceived) {
+ final String TIMED_OUT_FORMAT = "Timed out waiting for events from %s " +
+ "waited for time=%.1fms to receive totalEvents=%d at samplingRate=%.1fHz" +
+ " remainingEvents=%d received events=%d";
+ fail(String.format(TIMED_OUT_FORMAT, sensorName, totalTimeWaitedMs, numEvents,
+ 1000/minDelayMs, eventsRemaining, eventsReceived));
+ }
+
// Register for updates from each continuous mode sensor, wait for N events, call flush and
// wait for flushCompleteEvent before unregistering for the sensor.
- @TimeoutReq(minutes=10)
+ @TimeoutReq(minutes=20)
public void testBatchAndFlush() throws Exception {
try {
mWakeLock.acquire();
@@ -394,14 +419,14 @@
return;
}
final int numEvents = 500;
- final int rateUs = 20000; // DELAY_GAME
+ final int rateUs = 0; // DELAY_FASTEST
final int maxBatchReportLatencyUs = 10000000;
- final CountDownLatch eventReceived = new CountDownLatch(numEvents);
+ final CountDownLatch eventsRemaining = new CountDownLatch(numEvents);
final CountDownLatch flushReceived = new CountDownLatch(1);
SensorEventListener2 listener = new SensorEventListener2() {
@Override
public void onSensorChanged(SensorEvent event) {
- eventReceived.countDown();
+ eventsRemaining.countDown();
}
@Override
@@ -416,30 +441,62 @@
// Consider only continuous mode sensors for testing registerListener.
// For on-change sensors, call registerListener() so that the listener is associated
// with the sensor so that flush(listener) can be called on it.
- Log.i(TAG, "testBatch " + sensor.getName());
- boolean result = mSensorManager.registerListener(listener, sensor,
- rateUs, maxBatchReportLatencyUs, handler);
- assertTrue("registerListener failed " + sensor.getName(), result);
- // Wait for 500 events or N seconds before the test times out.
- if (sensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
- // Wait for approximately the time required to generate these events + a tolerance
- // of 10 seconds.
- long timeToWaitUs = (long)numEvents * rateUs + maxBatchReportLatencyUs +
- TIMEOUT_TOLERANCE_US;
- boolean countZero = eventReceived.await(timeToWaitUs, TimeUnit.MICROSECONDS);
- if (!countZero) {
- fail("Timed out waiting for events from " + sensor.getName());
+ try {
+ Log.i(TAG, "testBatch " + sensor.getName());
+ boolean result = mSensorManager.registerListener(listener, sensor,
+ rateUs, maxBatchReportLatencyUs, handler);
+ assertTrue("registerListener failed " + sensor.getName(), result);
+
+ // Wait for 500 events or N seconds before the test times out.
+ if (sensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
+ // Wait for approximately the time required to generate these events + a tolerance
+ // of 10 seconds.
+ long timeToWaitUs =
+ numEvents*(long)(sensor.getMinDelay()/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE)
+ + maxBatchReportLatencyUs + TIMEOUT_TOLERANCE_US;
+
+ long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs,
+ maxBatchReportLatencyUs, eventsRemaining);
+ if (eventsRemaining.getCount() > 0) {
+ failTimedOut(sensor.getName(), (double)totalTimeWaitedUs/1000, numEvents,
+ (double)sensor.getMinDelay()/1000,
+ eventsRemaining.getCount(), numEvents - eventsRemaining.getCount());
+ }
}
+ Log.i(TAG, "testFlush " + sensor.getName());
+ result = mSensorManager.flush(listener);
+ assertTrue("flush failed " + sensor.getName(), result);
+ boolean collectedAllEvents = flushReceived.await(TIMEOUT_TOLERANCE_US,
+ TimeUnit.MICROSECONDS);
+ if (!collectedAllEvents) {
+ fail("Timed out waiting for flushCompleteEvent from " + sensor.getName() +
+ " waitedFor="+ TIMEOUT_TOLERANCE_US/1000 + "ms");
+ }
+ Log.i(TAG, "testBatchAndFlush PASS " + sensor.getName());
+ } finally {
+ mSensorManager.unregisterListener(listener);
}
- Log.i(TAG, "testFlush " + sensor.getName());
- result = mSensorManager.flush(listener);
- assertTrue("flush failed " + sensor.getName(), result);
- boolean countZero = flushReceived.await(TIMEOUT_TOLERANCE_US, TimeUnit.MICROSECONDS);
- if (!countZero) {
- fail("Timed out waiting for flushCompleteEvent from " + sensor.getName());
- }
- mSensorManager.unregisterListener(listener);
- Log.i(TAG, "testBatchAndFlush pass " + sensor.getName());
+ }
+
+ // Wait till the CountDownLatch counts down to zero. If the events are not delivered within
+ // timetoWaitUs, wait an additional maxReportLantencyUs and check if the sensor is streaming
+ // data or not. If the sensor is not streaming at all, fail the test or else wait in increments
+ // of maxReportLantencyUs to collect sensor events.
+ private long waitToCollectAllEvents(long timeToWaitUs, int maxReportLatencyUs,
+ CountDownLatch eventsRemaining)
+ throws InterruptedException {
+ boolean collectedAllEvents = false;
+ long totalTimeWaitedUs = 0;
+ long remainingEvents;
+ final long INCREMENTAL_WAIT_US = maxReportLatencyUs + TimeUnit.SECONDS.toMicros(1);
+ do {
+ totalTimeWaitedUs += timeToWaitUs;
+ remainingEvents = eventsRemaining.getCount();
+ collectedAllEvents = eventsRemaining.await(timeToWaitUs, TimeUnit.MICROSECONDS);
+ timeToWaitUs = INCREMENTAL_WAIT_US;
+ } while (!collectedAllEvents &&
+ (remainingEvents - eventsRemaining.getCount() >=(long)INCREMENTAL_WAIT_US/1000000));
+ return totalTimeWaitedUs;
}
// Call registerListener for multiple sensors at a time and call flush.
@@ -450,14 +507,14 @@
return;
}
final int numEvents = 500;
- final int rateUs = 20000;
+ int rateUs = 0; // DELAY_FASTEST
final int maxBatchReportLatencyUs = 10000000;
- final CountDownLatch eventReceived = new CountDownLatch(numSensors * numEvents);
+ final CountDownLatch eventsRemaining = new CountDownLatch(numSensors * numEvents);
final CountDownLatch flushReceived = new CountDownLatch(numSensors);
SensorEventListener2 listener = new SensorEventListener2() {
@Override
public void onSensorChanged(SensorEvent event) {
- eventReceived.countDown();
+ eventsRemaining.countDown();
}
@Override
@@ -478,8 +535,9 @@
if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
continue;
}
+ rateUs = Math.max(sensor.getMinDelay(), rateUs);
boolean result = mSensorManager.registerListener(listener, sensor,
- SensorManager.SENSOR_DELAY_GAME, 10000000);
+ SensorManager.SENSOR_DELAY_FASTEST, maxBatchReportLatencyUs);
assertTrue("registerListener failed for " + sensor.getName(), result);
registeredSensors.append(sensor.getName());
registeredSensors.append(" ");
@@ -492,41 +550,50 @@
}
Log.i(TAG, "testBatchAndFlushWithMutipleSensors " + registeredSensors);
- long timeToWaitUs = (long)numEvents * rateUs + maxBatchReportLatencyUs +
- TIMEOUT_TOLERANCE_US;
- boolean countZero = eventReceived.await(timeToWaitUs, TimeUnit.MICROSECONDS);
- if (!countZero) {
- fail("Timed out waiting for events from " + registeredSensors.toString());
+ long timeToWaitUs =
+ numEvents*(long)(rateUs/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE) +
+ maxBatchReportLatencyUs + TIMEOUT_TOLERANCE_US;
+ long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs, maxBatchReportLatencyUs,
+ eventsRemaining);
+ if (eventsRemaining.getCount() > 0) {
+ failTimedOut(registeredSensors.toString(), (double)totalTimeWaitedUs/1000,
+ numEvents, (double)rateUs/1000, eventsRemaining.getCount(),
+ numEvents - eventsRemaining.getCount());
}
boolean result = mSensorManager.flush(listener);
assertTrue("flush failed " + registeredSensors.toString(), result);
- countZero = flushReceived.await(TIMEOUT_TOLERANCE_US, TimeUnit.MICROSECONDS);
- if (!countZero) {
+ boolean collectedFlushEvent =
+ flushReceived.await(TIMEOUT_TOLERANCE_US, TimeUnit.MICROSECONDS);
+ if (!collectedFlushEvent) {
fail("Timed out waiting for flushCompleteEvent from " +
- registeredSensors.toString());
+ registeredSensors.toString() + " waited for=" + timeToWaitUs/1000 + "ms");
}
- mSensorManager.unregisterListener(listener);
- Log.i(TAG, "testBatchAndFlushWithMutipleSensors passed");
+ Log.i(TAG, "testBatchAndFlushWithMutipleSensors PASS'd");
} finally {
+ mSensorManager.unregisterListener(listener);
mWakeLock.release();
}
}
private void assertSensorValues(Sensor sensor) {
- assertTrue(sensor.getMaximumRange() >= 0);
- assertTrue(sensor.getPower() >= 0);
- assertTrue(sensor.getResolution() >= 0);
- assertNotNull(sensor.getVendor());
- assertTrue(sensor.getVersion() > 0);
+ assertTrue("Max range must be positive. Range=" + sensor.getMaximumRange()
+ + " " + sensor.getName(), sensor.getMaximumRange() >= 0);
+ assertTrue("Max power must be positive. Power=" + sensor.getPower() + " " +
+ sensor.getName(), sensor.getPower() >= 0);
+ assertTrue("Max resolution must be positive. Resolution=" + sensor.getResolution() +
+ " " + sensor.getName(), sensor.getResolution() >= 0);
+ assertNotNull("Vendor name must not be null " + sensor.getName(), sensor.getVendor());
+ assertTrue("Version must be positive version=" + sensor.getVersion() + " " +
+ sensor.getName(), sensor.getVersion() > 0);
int fifoMaxEventCount = sensor.getFifoMaxEventCount();
int fifoReservedEventCount = sensor.getFifoReservedEventCount();
assertTrue(fifoMaxEventCount >= 0);
assertTrue(fifoReservedEventCount >= 0);
assertTrue(fifoReservedEventCount <= fifoMaxEventCount);
if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
- assertTrue("One shot sensors should have zero FIFO Size",
+ assertTrue("One shot sensors should have zero FIFO Size " + sensor.getName(),
sensor.getFifoMaxEventCount() == 0);
- assertTrue("One shot sensors should have zero FIFO Size",
+ assertTrue("One shot sensors should have zero FIFO Size " + sensor.getName(),
sensor.getFifoReservedEventCount() == 0);
}
}
diff --git a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
index 5e38842..586b9ef 100644
--- a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
+++ b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
@@ -335,11 +335,11 @@
}
/**
- * Converts (interleaves) YUV420 planar to NV12 (if hw) or NV21 (if sw).
+ * Converts (interleaves) YUV420 planar to NV12.
* Assumes packed, macroblock-aligned frame with no cropping
- * (visible/coded row length == stride). Swap U/V if |sw|.
+ * (visible/coded row length == stride).
*/
- private static byte[] YUV420ToNV(int width, int height, byte[] yuv, boolean sw) {
+ private static byte[] YUV420ToNV(int width, int height, byte[] yuv) {
byte[] nv = new byte[yuv.length];
// Y plane we just copy.
System.arraycopy(yuv, 0, nv, 0, width * height);
@@ -348,17 +348,9 @@
int u_offset = width * height;
int v_offset = u_offset + u_offset / 4;
int nv_offset = width * height;
- if (sw) {
- for (int i = 0; i < width * height / 4; i++) {
- nv[nv_offset++] = yuv[v_offset++];
- nv[nv_offset++] = yuv[u_offset++];
- }
- }
- else {
- for (int i = 0; i < width * height / 4; i++) {
- nv[nv_offset++] = yuv[u_offset++];
- nv[nv_offset++] = yuv[v_offset++];
- }
+ for (int i = 0; i < width * height / 4; i++) {
+ nv[nv_offset++] = yuv[u_offset++];
+ nv[nv_offset++] = yuv[v_offset++];
}
return nv;
}
@@ -788,7 +780,7 @@
// Convert YUV420 to NV12 if necessary
if (mProperties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
return YUV420ToNV(mStreamParams.frameWidth, mStreamParams.frameHeight,
- mSrcFrame, mProperties.isGoogleSwCodec());
+ mSrcFrame);
} else {
return mSrcFrame;
}
@@ -1390,7 +1382,7 @@
// Convert YUV420 to NV12 if necessary
if (properties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
srcFrame = YUV420ToNV(streamParams.frameWidth, streamParams.frameHeight,
- srcFrame, properties.isGoogleSwCodec());
+ srcFrame);
}
}
@@ -1652,8 +1644,7 @@
// Convert YUV420 to NV12 if necessary
if (codecProperties[i].colorFormat !=
CodecCapabilities.COLOR_FormatYUV420Planar) {
- srcFrame[i] = YUV420ToNV(params.frameWidth, params.frameHeight, srcFrame[i],
- codecProperties[i].isGoogleSwCodec());
+ srcFrame[i] = YUV420ToNV(params.frameWidth, params.frameHeight, srcFrame[i]);
}
}
diff --git a/tests/tests/tv/AndroidManifest.xml b/tests/tests/tv/AndroidManifest.xml
index fb84509..dc5d30a 100644
--- a/tests/tests/tv/AndroidManifest.xml
+++ b/tests/tests/tv/AndroidManifest.xml
@@ -81,6 +81,12 @@
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
</intent-filter>
</activity>
+ <activity android:name="android.tv.settings.cts.SettingsLeanbackStubActivity">
+ <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"
diff --git a/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java b/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java
index 4a9e141..f5cc2e1 100644
--- a/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java
@@ -133,7 +133,13 @@
return;
}
for (final TvInputInfo info : mPassthroughInputList) {
- mTvView.tune(info.getId(), TvContract.buildChannelUriForPassthroughInput(info.getId()));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTvView.tune(info.getId(),
+ TvContract.buildChannelUriForPassthroughInput(info.getId()));
+ }
+ });
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
@@ -156,7 +162,13 @@
for (int i = 0; i < mPassthroughInputList.size() * STRESS_FACTOR; ++i) {
final TvInputInfo info =
mPassthroughInputList.get(random.nextInt(mPassthroughInputList.size()));
- mTvView.tune(info.getId(), TvContract.buildChannelUriForPassthroughInput(info.getId()));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTvView.tune(info.getId(),
+ TvContract.buildChannelUriForPassthroughInput(info.getId()));
+ }
+ });
mInstrumentation.waitForIdleSync();
if (random.nextBoolean()) {
new PollingCheck(TIME_OUT) {
diff --git a/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackStubActivity.java b/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackStubActivity.java
new file mode 100644
index 0000000..171f709
--- /dev/null
+++ b/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackStubActivity.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 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.tv.settings.cts;
+
+import android.app.Activity;
+
+public class SettingsLeanbackStubActivity extends Activity {
+
+}
diff --git a/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackTest.java b/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackTest.java
new file mode 100644
index 0000000..c8b4a1b
--- /dev/null
+++ b/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 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.tv.settings.cts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.test.ActivityInstrumentationTestCase2;
+
+import java.util.List;
+
+public class SettingsLeanbackTest extends
+ ActivityInstrumentationTestCase2<SettingsLeanbackStubActivity> {
+
+ private static final String TAG = "SettingsLeanbackTest";
+
+ private static final String LEANBACK_SETTINGS_CATEGORY =
+ "android.intent.category.LEANBACK_SETTINGS";
+
+ private Activity mActivity;
+
+ public SettingsLeanbackTest() {
+ super(SettingsLeanbackStubActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ getInstrumentation().waitForIdleSync();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mActivity = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test if there is at least one activity that can handle LEANBACK_LAUNCHER
+ * category intent.
+ *
+ * @throws Exception
+ */
+ public void testLeanbackLauncherIntentCategory() throws Exception {
+ if (!Utils.hasLeanback(mActivity)) {
+ return;
+ }
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
+ assertIntentCanBeHandled(intent);
+ }
+
+ /**
+ * Test if there is at least one activity that can handle LEANBACK_SETTINGS
+ * category intent.
+ *
+ * @throws Exception
+ */
+ public void testLeanbackSettingsIntentCategory() throws Exception {
+ if (!Utils.hasLeanback(mActivity)) {
+ return;
+ }
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(LEANBACK_SETTINGS_CATEGORY);
+ assertIntentCanBeHandled(intent);
+ }
+
+ private void assertIntentCanBeHandled(final Intent intent) {
+ PackageManager packageManager = getActivity().getPackageManager();
+ List<ResolveInfo> resolveInfoList =
+ packageManager.queryIntentActivities(intent, 0);
+ assertNotNull(resolveInfoList);
+ // one or more activity can handle this intent.
+ assertTrue(resolveInfoList.size() > 0);
+ }
+}
diff --git a/tests/tests/tv/src/android/tv/settings/cts/Utils.java b/tests/tests/tv/src/android/tv/settings/cts/Utils.java
new file mode 100644
index 0000000..95ce795
--- /dev/null
+++ b/tests/tests/tv/src/android/tv/settings/cts/Utils.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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.tv.settings.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+public class Utils {
+ private Utils() { }
+
+ public static boolean hasFeature(Context context, String feature) {
+ return context.getPackageManager().hasSystemFeature(feature);
+ }
+
+ public static boolean hasLeanback(Context context) {
+ return hasFeature(context, PackageManager.FEATURE_LEANBACK);
+ }
+}