am 82a45527: Merge "SeccompTest: add note about kernels between 3.5 and 3.8"
* commit '82a4552791064064824e56eea5594b75b44f1170':
SeccompTest: add note about kernels between 3.5 and 3.8
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index de7e2bd..7bf8387 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -30,12 +30,14 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.FULLSCREEN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.camera.front"
android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus"
android:required="false" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -341,6 +343,30 @@
<meta-data android:name="test_required_features" android:value="android.hardware.camera.any"/>
</activity>
+ <activity
+ android:name=".camera.fov.PhotoCaptureActivity"
+ android:label="@string/camera_fov_calibration"
+ android:screenOrientation="landscape"
+ android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" >
+ <intent-filter android:label="@string/camera_fov_calibration" >
+ <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/test_category_camera" />
+ <meta-data android:name="test_required_features" android:value="android.hardware.sensor.gyroscope" />
+ <meta-data android:name="test_required_features" android:value="android.hardware.camera.any"/>
+ </activity>
+ <activity
+ android:name=".camera.fov.DetermineFovActivity"
+ android:label="@string/camera_fov_calibration"
+ android:screenOrientation="landscape"
+ android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" >
+ </activity>
+ <activity
+ android:name=".camera.fov.CalibrationPreferenceActivity"
+ android:label="@string/camera_fov_label_options" >
+ </activity>
+
<activity android:name=".usb.UsbAccessoryTestActivity"
android:label="@string/usb_accessory_test"
android:configChanges="keyboardHidden|orientation|screenSize">
diff --git a/apps/CtsVerifier/res/layout/camera_fov_calibration_determine_fov.xml b/apps/CtsVerifier/res/layout/camera_fov_calibration_determine_fov.xml
new file mode 100644
index 0000000..529fe39
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/camera_fov_calibration_determine_fov.xml
@@ -0,0 +1,31 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".DetermineFovActivity" >
+
+ <SurfaceView
+ android:id="@+id/camera_fov_photo_surface"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center" >
+ </SurfaceView>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ <SeekBar
+ android:id="@+id/camera_fov_seekBar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true" />
+ <Button
+ android:id="@+id/camera_fov_fov_done"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/camera_fov_calibration_done"
+ android:layout_above="@id/camera_fov_seekBar"
+ android:layout_alignParentRight="true" />
+ </RelativeLayout>
+
+</FrameLayout>
diff --git a/apps/CtsVerifier/res/layout/camera_fov_calibration_photo_capture.xml b/apps/CtsVerifier/res/layout/camera_fov_calibration_photo_capture.xml
new file mode 100644
index 0000000..712960f
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/camera_fov_calibration_photo_capture.xml
@@ -0,0 +1,48 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".PhotoCaptureActivity" >
+
+ <SurfaceView
+ android:id="@+id/camera_fov_camera_preview"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center" />
+
+ <com.android.cts.verifier.camera.fov.CameraPreviewView
+ android:id="@+id/camera_fov_preview_overlay"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <Button
+ android:id="@+id/camera_fov_settings_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:text="@string/camera_fov_settings_button_text" />
+
+ <TextView
+ android:id="@+id/camera_fov_tap_to_take_photo"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:padding="10sp"
+ android:text="@string/camera_fov_tap_to_take_photo"
+ android:textSize="18sp" />
+
+ <Spinner
+ android:id="@+id/camera_fov_resolution_selector"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:padding="10sp"
+ android:textSize="18sp" />
+ </RelativeLayout>
+
+</FrameLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 30d22a3..c6f74cf 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -551,4 +551,32 @@
connect ...</string>
<string name="p2p_waiting_for_peer_to_disconnect">Waiting for peer
to disconnect ...</string>
+
+ <string name="camera_fov_calibration">Camera FOV Calibration</string>
+ <string name="camera_fov_calibration_done">Done</string>
+ <string name="camera_fov_general_settings">General settings</string>
+ <string name="camera_fov_label_options">Settings</string>
+ <string name="camera_fov_tap_to_take_photo">Tap to calibrate</string>
+ <string name="camera_fov_marker_distance">Marker distance (in cm)</string>
+ <string name="camera_fov_marker_distance_description">The distance in centimeters between
+ the solid lines on the target pattern.</string>
+ <string name="camera_fov_target_distance">Target distance (in cm)</string>
+ <string name="camera_fov_target_distance_description">The distance in centimeters from the
+ device to the target pattern.</string>
+ <string name="camera_fov_settings_button_text">Setup</string>
+ <string name="camera_fov_displayed_fov_label">Displayed FOV : </string>
+ <string name="camera_fov_reported_fov_label">Reported FOV : </string>
+ <string name="camera_fov_panorama_wallpaper_title">Photo Sphere Live Wallpaper</string>
+ <string name="camera_fov_panorama_wallpaper_description">This live wallapper displays photo
+ spheres.</string>
+ <string name="camera_fov_select_panorama">Select panorama</string>
+ <string name="camera_fov_select_panorama_description">Select a panorama to display in the
+ live wallpaper.</string>
+ <string name="camera_fov_reset_panorama">Reset panorama</string>
+ <string name="camera_fov_reset_panorama_description">Resets the panorama to show the demo
+ file.</string>
+ <string name="camera_fov_enable_compass_mode">Enable compass mode</string>
+ <string name="camera_fov_enable_compass_mode_description">If enabled, the panorama orients
+ itself according to the current rotation of the device.</string>
+
</resources>
diff --git a/apps/CtsVerifier/res/xml/camera_fov_calibration_preferences.xml b/apps/CtsVerifier/res/xml/camera_fov_calibration_preferences.xml
new file mode 100644
index 0000000..7cf4c40
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/camera_fov_calibration_preferences.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orderingFromXml="true"
+ android:title="@string/camera_fov_label_options" >
+
+ <PreferenceCategory android:title="@string/camera_fov_general_settings" >
+ <EditTextPreference
+ android:defaultValue="36.8"
+ android:key="markerDistance"
+ android:numeric="decimal"
+ android:summary="@string/camera_fov_marker_distance_description"
+ android:title="@string/camera_fov_marker_distance" />
+ <EditTextPreference
+ android:defaultValue="99.7"
+ android:key="targetDistanceCm"
+ android:numeric="decimal"
+ android:summary="@string/camera_fov_target_distance_description"
+ android:title="@string/camera_fov_target_distance" />
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/CalibrationPreferenceActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/CalibrationPreferenceActivity.java
new file mode 100644
index 0000000..a3a980ef
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/CalibrationPreferenceActivity.java
@@ -0,0 +1,24 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.android.cts.verifier.camera.fov;
+
+import com.android.cts.verifier.R;
+
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+/**
+ * Preferences for the LightCycle calibration app.
+ *
+ * @author haeberling@google.com (Sascha Haeberling)
+ */
+public class CalibrationPreferenceActivity extends PreferenceActivity {
+ public static final String OPTION_MARKER_DISTANCE = "markerDistance";
+ public static final String OPTION_TARGET_DISTANCE = "targetDistanceCm";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.camera_fov_calibration_preferences);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/CameraPreviewView.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/CameraPreviewView.java
new file mode 100644
index 0000000..dcb6440
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/CameraPreviewView.java
@@ -0,0 +1,67 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+package com.android.cts.verifier.camera.fov;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * View that draws an overlay on the camera preview.
+ * @author settinger@google.com(Scott Ettinger)
+ */
+class CameraPreviewView extends View {
+
+ private static final int GRID_ALPHA = 50;
+ private static final int GRID_WIDTH = 50;
+ private Paint mPaint = new Paint();
+
+ public CameraPreviewView(Context context) {
+ super(context);
+ this.setWillNotDraw(false);
+ }
+
+ public CameraPreviewView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ this.setWillNotDraw(false);
+ }
+
+ public CameraPreviewView(
+ Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ this.setWillNotDraw(false);
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // Draw a single vertical line on the center of the image to help align
+ // the camera when setting up.
+ float centerX = canvas.getWidth() / 2.0f;
+ float centerY = canvas.getHeight() / 2.0f;
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(Color.GREEN);
+ mPaint.setStrokeWidth(3);
+ canvas.drawLine(centerX, 0, centerX, canvas.getHeight(), mPaint);
+
+ // Draw the transparent grid.
+ mPaint.setAlpha(GRID_ALPHA);
+ int vertLines = canvas.getWidth() / 2 / GRID_WIDTH;
+ int horizLines = canvas.getHeight() / 2 / GRID_WIDTH;
+ for (int i = 0; i < horizLines; ++i) {
+ int y = (int) centerY - i * GRID_WIDTH;
+ canvas.drawLine(0, y, canvas.getWidth(), y, mPaint);
+ y = (int) centerY + i * GRID_WIDTH;
+ canvas.drawLine(0, y, canvas.getWidth(), y, mPaint);
+ }
+ for (int i = 0; i < vertLines; ++i) {
+ int x = (int) centerX - i * GRID_WIDTH;
+ canvas.drawLine(x, 0, x, canvas.getHeight(), mPaint);
+ x = (int) centerX + i * GRID_WIDTH;
+ canvas.drawLine(x, 0, x, canvas.getHeight(), mPaint);
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/CtsTestHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/CtsTestHelper.java
new file mode 100644
index 0000000..c080729
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/CtsTestHelper.java
@@ -0,0 +1,60 @@
+/*
+ * 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.camera.fov;
+
+import android.app.Activity;
+import android.content.Intent;
+
+import java.util.List;
+
+class CtsTestHelper {
+
+ private static final String REPORTED_FOV_EXTRA = "lightcycle.reported_fov";
+ private static final String MEASURED_FOV_EXTRA = "lightcycle.measured_fov";
+
+ public static void storeCtsTestResult(Activity activity, float reportedFOV, float measuredFOV) {
+ Intent it = new Intent();
+ it.putExtra(REPORTED_FOV_EXTRA, reportedFOV);
+ it.putExtra(MEASURED_FOV_EXTRA, measuredFOV);
+ activity.setResult(Activity.RESULT_OK, it);
+ }
+
+ public static float getMeasuredFOV(Intent intent) {
+ return intent.getFloatExtra(MEASURED_FOV_EXTRA, -1f);
+ }
+
+ public static float getReportedFOV(Intent intent) {
+ return intent.getFloatExtra(REPORTED_FOV_EXTRA, -1f);
+ }
+
+ public static boolean isResultPassed(float reportedFOV, float measuredFOV) {
+ if (Math.abs(reportedFOV - measuredFOV) < 2f) return true;
+ return false;
+ }
+
+ public static String getTestDetails(List<SelectableResolution> resolutions) {
+ String details = "PhotoSphere FOV test result:\n";
+ for (int i = 0; i < resolutions.size(); i++) {
+ SelectableResolution res = resolutions.get(i);
+ details += "Resolution:" + res.width + 'x' + res.height
+ + ", Measured FOV = " + res.measuredFOV + '\n';
+
+ }
+
+ return details;
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/DetermineFovActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/DetermineFovActivity.java
new file mode 100644
index 0000000..8b989e1
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/DetermineFovActivity.java
@@ -0,0 +1,255 @@
+/*
+ * 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.camera.fov;
+
+import com.android.cts.verifier.R;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.widget.Button;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * Shows the picture taken and lets the user specify the field of view (FOV).
+ */
+public class DetermineFovActivity extends Activity {
+
+ private static final float FOV_ADJUSTMENT_RANGE = 20;
+ private static final int SEEKBAR_MAX_VALUE = 100;
+ private static final float TEXT_SIZE = 16;
+ private static final float TEXT_PADDING = 0.2f;
+ private static final String DEFAULT_MARKER_DISTANCE = "36.8";
+ private static final String DEFAULT_TARGET_DISTANCE = "99.7";
+
+ private float mMarkerDistanceCm;
+ private SurfaceView mSurfaceView;
+ private SurfaceHolder mSurfaceHolder;
+ private Bitmap mPhotoBitmap;
+ private float mFovMinDegrees;
+ private float mFovMaxDegrees;
+ private float mFovDegrees;
+ private float mReportedFovDegrees;
+ private SeekBar mSeekBar;
+ private Button mDoneButton;
+ private float mTargetDistanceCm;
+ private String mMeasuredText;
+ private String mReportedText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.camera_fov_calibration_determine_fov);
+ File pictureFile = PhotoCaptureActivity.getPictureFile(this);
+ try {
+ mPhotoBitmap =
+ BitmapFactory.decodeStream(new FileInputStream(pictureFile));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ mSurfaceView = (SurfaceView) findViewById(R.id.camera_fov_photo_surface);
+ mSurfaceHolder = mSurfaceView.getHolder();
+ mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {}
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ drawContents();
+ }
+
+ @Override
+ public void surfaceChanged(
+ SurfaceHolder holder, int format, int width, int height) {
+ drawContents();
+ }
+ });
+
+ mSeekBar = (SeekBar) findViewById(R.id.camera_fov_seekBar);
+ mSeekBar.setMax(SEEKBAR_MAX_VALUE);
+ mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {}
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {}
+
+ @Override
+ public void onProgressChanged(
+ SeekBar seekBar, int progress, boolean fromUser) {
+ mFovDegrees = seekBarProgressToFovDegrees(progress);
+ drawContents();
+ }
+ });
+
+ mDoneButton = (Button) findViewById(R.id.camera_fov_fov_done);
+ mDoneButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setResult(RESULT_OK);
+ CtsTestHelper.storeCtsTestResult(DetermineFovActivity.this,
+ mReportedFovDegrees, mFovDegrees);
+ finish();
+ }
+ });
+ }
+
+ private int fovToSeekBarProgress(float fovDegrees) {
+ return Math.round((fovDegrees - mFovMinDegrees)
+ / (mFovMaxDegrees - mFovMinDegrees) * SEEKBAR_MAX_VALUE);
+ }
+
+ private float seekBarProgressToFovDegrees(int progress) {
+ float degrees = mFovMinDegrees + (float) progress / SEEKBAR_MAX_VALUE
+ * (mFovMaxDegrees - mFovMinDegrees);
+ // keep only 2 decimal places.
+ return (int) (degrees * 100) / 100.0f;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ setResult(RESULT_CANCELED);
+ mMarkerDistanceCm = getMarkerDistance();
+ mTargetDistanceCm = getTargetDistance();
+ mReportedFovDegrees = PhotoCaptureActivity.getReportedFovDegrees();
+
+ mFovDegrees = mReportedFovDegrees > 80 ? 60 : mReportedFovDegrees;
+ mFovMaxDegrees = mFovDegrees + FOV_ADJUSTMENT_RANGE / 2;
+ mFovMinDegrees = mFovDegrees - FOV_ADJUSTMENT_RANGE / 2;
+
+ mMeasuredText = getResources().getString(R.string.camera_fov_displayed_fov_label);
+ mReportedText = getResources().getString(R.string.camera_fov_reported_fov_label);
+
+ mSeekBar.setProgress(fovToSeekBarProgress(mFovDegrees));
+ drawContents();
+ }
+
+ private float getMarkerDistance() {
+ // Get the marker distance from the preferences.
+ SharedPreferences prefs =
+ PreferenceManager.getDefaultSharedPreferences(this);
+ return Float.parseFloat(prefs.getString(
+ CalibrationPreferenceActivity.OPTION_MARKER_DISTANCE,
+ DEFAULT_MARKER_DISTANCE));
+ }
+
+ private float getTargetDistance() {
+ // Get the marker distance from the preferences.
+ SharedPreferences prefs =
+ PreferenceManager.getDefaultSharedPreferences(this);
+ return Float.parseFloat(prefs.getString(
+ CalibrationPreferenceActivity.OPTION_TARGET_DISTANCE,
+ DEFAULT_TARGET_DISTANCE));
+ }
+
+ private float focalLengthPixels(float fovDegrees, float imageWidth) {
+ return (float) (imageWidth
+ / (2 * Math.tan(fovDegrees / 2 * Math.PI / 180.0f)));
+ }
+
+ private void drawContents() {
+ SurfaceHolder holder = mSurfaceView.getHolder();
+ Canvas canvas = holder.lockCanvas();
+ if (canvas == null || mPhotoBitmap == null) {
+ return;
+ }
+
+ int canvasWidth = canvas.getWidth();
+ int canvasHeight = canvas.getHeight();
+ int photoWidth = mPhotoBitmap.getWidth();
+ int photoHeight = mPhotoBitmap.getHeight();
+ RectF drawRect = new RectF();
+
+ // Determine if the canvas aspect ratio is larger than that of the photo.
+ float scale = (float) canvasWidth / photoWidth;
+ int scaledHeight = (int) (scale * photoHeight);
+ if (scaledHeight < canvasHeight) {
+ // If the aspect ratio is smaller, set the destination rectangle to pad
+ // vertically.
+ int pad = (canvasHeight - scaledHeight) / 2;
+ drawRect.set(0, pad, canvasWidth, pad + scaledHeight - 1);
+ } else {
+ // Set the destination rectangle to pad horizontally.
+ scale = (float) canvasHeight / photoHeight;
+ float scaledWidth = scale * photoWidth;
+ float pad = (canvasWidth - scaledWidth) / 2;
+ drawRect.set(pad, 0, pad + scaledWidth - 1, canvasHeight);
+ }
+
+ // Draw the photo.
+ canvas.drawColor(Color.BLACK);
+ canvas.drawBitmap(mPhotoBitmap, null, drawRect, null);
+
+ // Draw the fov indicator text.
+ Paint paint = new Paint();
+ paint.setColor(0xffffffff);
+ float textSize = TEXT_SIZE * DetermineFovActivity.this.getResources()
+ .getDisplayMetrics().scaledDensity;
+ paint.setTextSize(textSize);
+ canvas.drawText(mMeasuredText + " " + mFovDegrees + " degrees.", textSize,
+ 2 * textSize * (1.0f + TEXT_PADDING), paint);
+ canvas.drawText(mReportedText + " " + mReportedFovDegrees + " degrees.",
+ textSize, textSize * (1.0f + TEXT_PADDING), paint);
+
+ // Draw the image center circle.
+ paint.setColor(Color.BLACK);
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeWidth(3);
+ float dstWidth = drawRect.right - drawRect.left + 1;
+ float dstHeight = drawRect.bottom - drawRect.top + 1;
+ float centerX = drawRect.left + dstWidth / 2;
+ canvas.drawLine(centerX, drawRect.top, centerX, drawRect.bottom, paint);
+
+ // Project the markers into the scaled image with the given field of view.
+ float markerX = mMarkerDistanceCm / 2;
+ float markerZ = mTargetDistanceCm;
+ float focalLength = focalLengthPixels(mFovDegrees, dstWidth);
+ float dx = markerX / markerZ * focalLength;
+ float projectedMarkerLeft = dstWidth / 2 - dx;
+ float projectedMarkerRight = dstWidth / 2 + dx;
+
+ // Draw the marker lines over the image.
+ paint.setColor(Color.GREEN);
+ paint.setStrokeWidth(2);
+ float markerImageLeft = projectedMarkerLeft + drawRect.left;
+ canvas.drawLine(
+ markerImageLeft, drawRect.top, markerImageLeft, drawRect.bottom, paint);
+ float markerImageRight = projectedMarkerRight + drawRect.left;
+ canvas.drawLine(markerImageRight, drawRect.top, markerImageRight,
+ drawRect.bottom, paint);
+
+ holder.unlockCanvasAndPost(canvas);
+ }
+}
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
new file mode 100644
index 0000000..c5957c0
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
@@ -0,0 +1,339 @@
+/*
+ * 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.camera.fov;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.hardware.Camera;
+import android.hardware.Camera.PictureCallback;
+import android.hardware.Camera.Size;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.TestResult;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An activity for showing the camera preview and taking a picture.
+ */
+public class PhotoCaptureActivity extends Activity
+implements PictureCallback, SurfaceHolder.Callback {
+ private static final String TAG = PhotoCaptureActivity.class.getSimpleName();
+ private static final int FOV_REQUEST_CODE = 1006;
+ private static final String PICTURE_FILENAME = "photo.jpg";
+ private static float mReportedFovDegrees = 0;
+
+ private SurfaceView mPreview;
+ private SurfaceHolder mSurfaceHolder;
+ private Spinner mResolutionSpinner;
+ private List<SelectableResolution> mSupportedResolutions;
+ private ArrayAdapter<SelectableResolution> mAdapter;
+
+ private Camera mCamera;
+ private boolean mCameraInitialized = false;
+ private boolean mPreviewActive = false;
+ private int mResolutionSpinnerIndex = -1;
+ private WakeLock mWakeLock;
+
+ public static File getPictureFile(Context context) {
+ return new File(context.getExternalCacheDir(), PICTURE_FILENAME);
+ }
+
+ public static float getReportedFovDegrees() {
+ return mReportedFovDegrees;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.camera_fov_calibration_photo_capture);
+
+ mPreview = (SurfaceView) findViewById(R.id.camera_fov_camera_preview);
+ mSurfaceHolder = mPreview.getHolder();
+ mSurfaceHolder.addCallback(this);
+
+ // This is required for older versions of Android hardware.
+ mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+
+ TextView textView = (TextView) findViewById(R.id.camera_fov_tap_to_take_photo);
+ textView.setTextColor(Color.WHITE);
+
+ Button setupButton = (Button) findViewById(R.id.camera_fov_settings_button);
+ setupButton.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ startActivity(new Intent(
+ PhotoCaptureActivity.this, CalibrationPreferenceActivity.class));
+ }
+ });
+
+ View previewView = findViewById(R.id.camera_fov_preview_overlay);
+ previewView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mCamera.takePicture(null, null, PhotoCaptureActivity.this);
+ }
+ });
+
+ mResolutionSpinner = (Spinner) findViewById(R.id.camera_fov_resolution_selector);
+ mResolutionSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(
+ AdapterView<?> parent, View view, int position, long id) {
+ if (mSupportedResolutions != null) {
+ SelectableResolution resolution = mSupportedResolutions.get(position);
+
+ Camera.Parameters params = mCamera.getParameters();
+ params.setPictureSize(resolution.width, resolution.height);
+ mCamera.setParameters(params);
+ mResolutionSpinnerIndex = position;
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> arg0) {}
+ });
+ }
+
+ /**
+ * Get the best supported focus mode.
+ *
+ * @param camera - Android camera object.
+ * @return the best supported focus mode.
+ */
+ protected String getFocusMode(Camera camera) {
+ List<String> modes = camera.getParameters().getSupportedFocusModes();
+ if (modes != null) {
+ if (modes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
+ Log.v(TAG, "Using Focus mode infinity");
+ return Camera.Parameters.FOCUS_MODE_INFINITY;
+ }
+ if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
+ Log.v(TAG, "Using Focus mode fixed");
+ return Camera.Parameters.FOCUS_MODE_FIXED;
+ }
+ }
+ Log.v(TAG, "Using Focus mode auto.");
+ return Camera.Parameters.FOCUS_MODE_AUTO;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mCamera = Camera.open();
+
+ // Keep the device from going to sleep.
+ PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
+ mWakeLock.acquire();
+
+ if (mSupportedResolutions == null) {
+ // Get the supported picture sizes and fill the spinner.
+ List<Size> supportedSizes =
+ mCamera.getParameters().getSupportedPictureSizes();
+ mSupportedResolutions = new ArrayList<SelectableResolution>();
+ for (Size size : supportedSizes) {
+ mSupportedResolutions.add(
+ new SelectableResolution(size.width, size.height));
+ }
+ }
+
+ // find teh first untested one.
+ for (mResolutionSpinnerIndex = 0;
+ mResolutionSpinnerIndex < mSupportedResolutions.size();
+ mResolutionSpinnerIndex++) {
+ if (!mSupportedResolutions.get(mResolutionSpinnerIndex).tested) break;
+ }
+
+ mAdapter = new ArrayAdapter<SelectableResolution>(
+ this, android.R.layout.simple_spinner_dropdown_item,
+ mSupportedResolutions);
+ mResolutionSpinner.setAdapter(mAdapter);
+
+ mResolutionSpinner.setSelection(mResolutionSpinnerIndex);
+ setResult(RESULT_CANCELED);
+ }
+
+ @Override
+ public void onPause() {
+ if (mPreviewActive) {
+ mCamera.stopPreview();
+ }
+
+ mCamera.release();
+ mCamera = null;
+ mPreviewActive = false;
+ mWakeLock.release();
+
+ super.onPause();
+ }
+
+ @Override
+ public void onPictureTaken(byte[] data, Camera camera) {
+ File pictureFile = getPictureFile(this);
+ Camera.Parameters params = mCamera.getParameters();
+ mReportedFovDegrees = params.getHorizontalViewAngle();
+ try {
+ FileOutputStream fos = new FileOutputStream(pictureFile);
+ fos.write(data);
+ fos.close();
+ Log.d(TAG, "File saved to " + pictureFile.getAbsolutePath());
+
+ // Start activity which will use he taken picture to determine the FOV.
+ startActivityForResult(new Intent(this, DetermineFovActivity.class),
+ FOV_REQUEST_CODE + mResolutionSpinnerIndex, null);
+ } catch (IOException e) {
+ Log.e(TAG, "Could not save picture file.", e);
+ Toast.makeText(this, "Could not save picture file: " + e.getMessage(),
+ Toast.LENGTH_LONG).show();
+ return;
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode != RESULT_OK) return;
+ int testIndex = requestCode - FOV_REQUEST_CODE;
+ SelectableResolution res = mSupportedResolutions.get(testIndex);
+ res.tested = true;
+ float reportedFOV = CtsTestHelper.getReportedFOV(data);
+ float measuredFOV = CtsTestHelper.getMeasuredFOV(data);
+ res.measuredFOV = measuredFOV;
+ if (CtsTestHelper.isResultPassed(reportedFOV, measuredFOV)) {
+ res.passed = true;
+ }
+
+ boolean allTested = true;
+ for (int i = 0; i < mSupportedResolutions.size(); i++) {
+ if (!mSupportedResolutions.get(i).tested) {
+ allTested = false;
+ break;
+ }
+ }
+ if (!allTested) {
+ mAdapter.notifyDataSetChanged();
+ return;
+ }
+
+ boolean allPassed = true;
+ for (int i = 0; i < mSupportedResolutions.size(); i++) {
+ if (!mSupportedResolutions.get(i).passed) {
+ allPassed = false;
+ break;
+ }
+ }
+ if (allPassed) {
+ TestResult.setPassedResult(this, getClass().getName(),
+ CtsTestHelper.getTestDetails(mSupportedResolutions));
+ } else {
+ TestResult.setFailedResult(this, getClass().getName(),
+ CtsTestHelper.getTestDetails(mSupportedResolutions));
+ }
+ finish();
+ }
+
+ @Override
+ public void surfaceChanged(
+ SurfaceHolder holder, int format, int width, int height) {
+ if (mCamera == null || mSurfaceHolder.getSurface() == null) {
+ return;
+ }
+
+ try {
+ mCamera.setPreviewDisplay(mSurfaceHolder);
+ } catch (Throwable t) {
+ Log.e("TAG", "Could not set preview display", t);
+ Toast.makeText(this, t.getMessage(), Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ // The picture size is taken and set from the spinner selection callback.
+ Camera.Parameters params = mCamera.getParameters();
+ params.setJpegThumbnailSize(0, 0);
+ params.setJpegQuality(100);
+ params.setFocusMode(getFocusMode(mCamera));
+ params.setZoom(0);
+
+ Camera.Size size = getBestPreviewSize(width, height, params);
+ if (size != null) {
+ params.setPreviewSize(size.width, size.height);
+ mCamera.setParameters(params);
+ mCameraInitialized = true;
+ }
+ startPreview();
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ // Nothing to do.
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // Nothing to do.
+ }
+
+ private void startPreview() {
+ if (mCameraInitialized && mCamera != null) {
+ mCamera.startPreview();
+ mPreviewActive = true;
+ }
+ }
+
+ private Camera.Size getBestPreviewSize(
+ int width, int height, Camera.Parameters parameters) {
+ Camera.Size result = null;
+
+ for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
+ if (size.width <= width && size.height <= height) {
+ if (result == null) {
+ result = size;
+ } else {
+ int resultArea = result.width * result.height;
+ int newArea = size.width * size.height;
+
+ if (newArea > resultArea) {
+ result = size;
+ }
+ }
+ }
+ }
+ return (result);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/SelectableResolution.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/SelectableResolution.java
new file mode 100644
index 0000000..5e87eee
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/SelectableResolution.java
@@ -0,0 +1,40 @@
+/*
+ * 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.camera.fov;
+
+/**
+ * A resolution to be used in the adapter that feeds the resolution spinner.
+ */
+public class SelectableResolution {
+ public final int width;
+ public final int height;
+ public boolean passed;
+ public boolean tested;
+ public float measuredFOV;
+
+ public SelectableResolution(int width, int height) {
+ this.width = width;
+ this.height = height;
+ passed = false;
+ tested = false;
+ }
+
+ @Override
+ public String toString() {
+ return width + " x " + height + " - " + (!tested ? "untested" : "done");
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java
index 900664f..aea874b 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java
@@ -20,6 +20,10 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
/**
* Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
String[] selectionArgs) {
return 0;
}
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ return ParcelFileDescriptor.open(
+ new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
index 97bd827..bb88c34 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
@@ -20,6 +20,10 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
/**
* Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
String[] selectionArgs) {
return 0;
}
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ return ParcelFileDescriptor.open(
+ new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java
index 4f301a3..13151f5 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java
@@ -4,6 +4,10 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
/**
* Empty content provider, all permissions are enforced in manifest
@@ -42,4 +46,10 @@
String[] selectionArgs) {
return 0;
}
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ return ParcelFileDescriptor.open(
+ new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java
index 3206206..41dd889 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java
@@ -20,6 +20,10 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
/**
* Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
String[] selectionArgs) {
return 0;
}
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ return ParcelFileDescriptor.open(
+ new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
index 64ec6e7..6ce5239 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
@@ -20,6 +20,10 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
/**
* Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
String[] selectionArgs) {
return 0;
}
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ return ParcelFileDescriptor.open(
+ new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
index f9ae96b..372b399 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
@@ -20,6 +20,10 @@
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
/**
* Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
String[] selectionArgs) {
return 0;
}
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ return ParcelFileDescriptor.open(
+ new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
index a6495a9..e7d333c 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
@@ -19,6 +19,7 @@
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -28,6 +29,8 @@
import android.test.AndroidTestCase;
import android.util.Log;
+import java.io.IOException;
+
/**
* Tests that signature-enforced permissions cannot be accessed by apps signed
* with different certs than app that declares the permission.
@@ -88,18 +91,71 @@
}
}
- private void assertWritingContentUriNotAllowed(Uri uri, String msg) {
+ private void assertOpenFileDescriptorModeNotAllowed(Uri uri, String msg, String mode) {
try {
- getContext().getContentResolver().insert(uri, new ContentValues());
+ getContext().getContentResolver().openFileDescriptor(uri, mode).close();
fail("expected SecurityException writing " + uri + ": " + msg);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
} catch (SecurityException expected) {
assertNotNull("security exception's error message.", expected.getMessage());
}
}
- private void assertWritingContentUriAllowed(Uri uri) {
+ public void assertWritingContentUriNotAllowed(Uri uri, String msg) {
+ final ContentResolver resolver = getContext().getContentResolver();
try {
- getContext().getContentResolver().insert(uri, new ContentValues());
+ resolver.insert(uri, new ContentValues());
+ fail("expected SecurityException inserting " + uri + ": " + msg);
+ } catch (SecurityException expected) {
+ assertNotNull("security exception's error message.", expected.getMessage());
+ }
+
+ try {
+ resolver.update(uri, new ContentValues(), null, null);
+ fail("expected SecurityException updating " + uri + ": " + msg);
+ } catch (SecurityException expected) {
+ assertNotNull("security exception's error message.", expected.getMessage());
+ }
+
+ try {
+ resolver.delete(uri, null, null);
+ fail("expected SecurityException deleting " + uri + ": " + msg);
+ } catch (SecurityException expected) {
+ assertNotNull("security exception's error message.", expected.getMessage());
+ }
+
+ try {
+ getContext().getContentResolver().openOutputStream(uri).close();
+ fail("expected SecurityException writing " + uri + ": " + msg);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ } catch (SecurityException expected) {
+ assertNotNull("security exception's error message.", expected.getMessage());
+ }
+
+ assertOpenFileDescriptorModeNotAllowed(uri, msg, "w");
+ assertOpenFileDescriptorModeNotAllowed(uri, msg, "wt");
+ assertOpenFileDescriptorModeNotAllowed(uri, msg, "wa");
+ assertOpenFileDescriptorModeNotAllowed(uri, msg, "rw");
+ assertOpenFileDescriptorModeNotAllowed(uri, msg, "rwt");
+ }
+
+ private void assertWritingContentUriAllowed(Uri uri) {
+ final ContentResolver resolver = getContext().getContentResolver();
+ try {
+ resolver.insert(uri, new ContentValues());
+ resolver.update(uri, new ContentValues(), null, null);
+ resolver.delete(uri, null, null);
+
+ resolver.openOutputStream(uri).close();
+ resolver.openFileDescriptor(uri, "w").close();
+ resolver.openFileDescriptor(uri, "wt").close();
+ resolver.openFileDescriptor(uri, "wa").close();
+ resolver.openFileDescriptor(uri, "rw").close();
+ resolver.openFileDescriptor(uri, "rwt").close();
+ } catch (IOException e) {
+ fail("unexpected IOException writing " + uri + ": " + e.getMessage());
} catch (SecurityException e) {
fail("unexpected SecurityException writing " + uri + ": " + e.getMessage());
}
diff --git a/tests/src/android/view/inputmethod/cts/InputMethodInfoStub.java b/tests/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java
similarity index 84%
rename from tests/src/android/view/inputmethod/cts/InputMethodInfoStub.java
rename to tests/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java
index 0eeefbe..58aa364 100644
--- a/tests/src/android/view/inputmethod/cts/InputMethodInfoStub.java
+++ b/tests/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java
@@ -16,8 +16,8 @@
package android.view.inputmethod.cts;
-import android.inputmethodservice.InputMethodService;
+import android.preference.PreferenceActivity;
-public class InputMethodInfoStub extends InputMethodService {
+public class InputMethodSettingsActivityStub extends PreferenceActivity {
}
diff --git a/tests/tests/holo/AndroidManifest.xml b/tests/tests/holo/AndroidManifest.xml
index 7eb899c..4a03ba3 100644
--- a/tests/tests/holo/AndroidManifest.xml
+++ b/tests/tests/holo/AndroidManifest.xml
@@ -43,7 +43,12 @@
<activity android:name="android.holo.cts.ThemeTestActivity"
android:configChanges="keyboardHidden|orientation|screenSize|mcc|mnc"
android:screenOrientation="nosensor"
- android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+ android:theme="@android:style/Theme.Translucent.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
<activity android:name="android.holo.cts.LayoutTestActivity"
android:configChanges="keyboardHidden|orientation|screenSize|mcc|mnc"
diff --git a/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java b/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java
index 08659df..b7fdd1d 100644
--- a/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java
+++ b/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java
@@ -85,7 +85,8 @@
int layoutIndex = getIntent().getIntExtra(EXTRA_LAYOUT_INDEX, -1);
int adapterMode = getIntent().getIntExtra(EXTRA_LAYOUT_ADAPTER_MODE, -1);
- Log.i(TAG, "Theme index: " + themeIndex + " Layout index: " + layoutIndex);
+ Log.i(TAG, "Theme index: " + themeIndex + " Layout index: " + layoutIndex +
+ " adapter mode: " + adapterMode);
if (themeIndex < 0 && layoutIndex < 0) {
mIterator = new AllThemesIterator(task, adapterMode);
@@ -109,6 +110,11 @@
startActivityForResult(intent, mRequestCode);
} else {
mResultFuture.set(mPendingResult);
+ if (mRequestCode == GENERATE_BITMAP_REQUEST_CODE) {
+ // finish with result so that generated bitmaps can be captured automatically
+ setResult(0);
+ finish();
+ }
}
}
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index 32fd18d..4eb47c2 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -23,10 +23,12 @@
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.LargeTest;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
@@ -523,7 +525,8 @@
@LargeTest
public void testReadingSysFilesDoesntFail() throws Exception {
- tryToReadFromAllIn(new File("/sys"));
+ // TODO: fix b/8148087
+ // tryToReadFromAllIn(new File("/sys"));
}
private static void tryToReadFromAllIn(File dir) throws IOException {
@@ -615,6 +618,42 @@
return retval;
}
+ public void testSystemMountedRO() throws IOException {
+ assertSystemMountedROIn("/proc/self/mounts");
+ }
+
+ public void testSystemMountedRO_init() throws IOException {
+ assertSystemMountedROIn("/proc/1/mounts");
+ }
+
+ /**
+ * Scan through {@code filename}, looking for the /system line. If the line
+ * has "ro" in the 4th column, then we know the filesystem is mounted read-only.
+ */
+ private static void assertSystemMountedROIn(String filename) throws IOException {
+ BufferedReader br = new BufferedReader(new FileReader(filename));
+ String line;
+ boolean foundSystem = false;
+ while((line = br.readLine()) != null) {
+ String[] fields = line.split(" ");
+ String mountPoint = fields[1];
+ if ("/system".equals(mountPoint)) {
+ foundSystem = true;
+ String all_options = fields[3];
+ boolean foundRo = false;
+ String[] options = all_options.split(",");
+ for (String option : options) {
+ if ("ro".equals(option)) {
+ foundRo = true;
+ break;
+ }
+ }
+ assertTrue(mountPoint + " is not mounted read-only", foundRo);
+ }
+ }
+ assertTrue("Cannot find /system partition", foundSystem);
+ }
+
public void testAllBlockDevicesAreSecure() throws Exception {
Set<File> insecure = getAllInsecureBlockDevicesInDirAndSubdir(new File("/dev"));
assertTrue("Found insecure: " + insecure.toString(),
diff --git a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
index da9057e..80dffba 100644
--- a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
@@ -110,6 +110,33 @@
}
/**
+ * Verify that get cell location requires permissions.
+ * <p>
+ * Requires Permission: {@link
+ * android.Manifest.permission#ACCESS_COARSE_LOCATION.}
+ */
+ @SmallTest
+ public void testListenCellLocation2() {
+ TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(
+ Context.TELEPHONY_SERVICE);
+ PhoneStateListener phoneStateListener = new PhoneStateListener();
+
+ try {
+ telephonyManager.getNeighboringCellInfo();
+ fail("TelephonyManager.getNeighbouringCellInfo did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ telephonyManager.getAllCellInfo();
+ fail("TelephonyManager.getAllCellInfo did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
* Helper method to verify that calling requestLocationUpdates with given
* provider throws SecurityException.
*
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
index 00a8dea..722c1b3 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
@@ -16,7 +16,6 @@
package android.view.inputmethod.cts;
-
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -27,6 +26,7 @@
import android.util.Printer;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
import org.xmlpull.v1.XmlPullParserException;
@@ -40,14 +40,40 @@
private CharSequence mLabel;
private String mSettingsActivity;
+ private int mSubtypeNameResId;
+ private int mSubtypeIconResId;
+ private String mSubtypeLocale;
+ private String mSubtypeMode;
+ private String mSubtypeExtraValue_key;
+ private String mSubtypeExtraValue_value;
+ private String mSubtypeExtraValue;
+ private boolean mSubtypeIsAuxiliary;
+ private boolean mSubtypeOverridesImplicitlyEnabledSubtype;
+ private int mSubtypeId;
+ private InputMethodSubtype mInputMethodSubtype;
+
@Override
protected void setUp() throws Exception {
super.setUp();
mPackageName = mContext.getPackageName();
- mClassName = InputMethodInfoStub.class.getName();
+ mClassName = InputMethodSettingsActivityStub.class.getName();
mLabel = "test";
- mSettingsActivity = "android.view.inputmethod.cts.InputMethodInfoStub";
+ mSettingsActivity = "android.view.inputmethod.cts.InputMethodSettingsActivityStub";
mInputMethodInfo = new InputMethodInfo(mPackageName, mClassName, mLabel, mSettingsActivity);
+
+ mSubtypeNameResId = 0;
+ mSubtypeIconResId = 0;
+ mSubtypeLocale = "en_US";
+ mSubtypeMode = "keyboard";
+ mSubtypeExtraValue_key = "key1";
+ mSubtypeExtraValue_value = "value1";
+ mSubtypeExtraValue = "tag," + mSubtypeExtraValue_key + "=" + mSubtypeExtraValue_value;
+ mSubtypeIsAuxiliary = false;
+ mSubtypeOverridesImplicitlyEnabledSubtype = false;
+ mSubtypeId = 99;
+ mInputMethodSubtype = new InputMethodSubtype(mSubtypeNameResId, mSubtypeIconResId,
+ mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue, mSubtypeIsAuxiliary,
+ mSubtypeOverridesImplicitlyEnabledSubtype, mSubtypeId);
}
public void testInputMethodInfoProperties() throws XmlPullParserException, IOException {
@@ -58,7 +84,7 @@
assertEquals(0, mInputMethodInfo.getIsDefaultResourceId());
Intent intent = new Intent(InputMethod.SERVICE_INTERFACE);
- intent.setClass(mContext, InputMethodInfoStub.class);
+ intent.setClass(mContext, InputMethodSettingsActivityStub.class);
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> ris = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
for (int i = 0; i < ris.size(); i++) {
@@ -69,6 +95,22 @@
}
}
+ public void testInputMethodSubtypeProperties() {
+ // TODO: Test InputMethodSubtype.getDisplayName()
+ assertEquals(mSubtypeNameResId, mInputMethodSubtype.getNameResId());
+ assertEquals(mSubtypeIconResId, mInputMethodSubtype.getIconResId());
+ assertEquals(mSubtypeLocale, mInputMethodSubtype.getLocale());
+ assertEquals(mSubtypeMode, mInputMethodSubtype.getMode());
+ assertEquals(mSubtypeExtraValue, mInputMethodSubtype.getExtraValue());
+ assertTrue(mInputMethodSubtype.containsExtraValueKey(mSubtypeExtraValue_key));
+ assertEquals(mSubtypeExtraValue_value,
+ mInputMethodSubtype.getExtraValueOf(mSubtypeExtraValue_key));
+ assertEquals(mSubtypeIsAuxiliary, mInputMethodSubtype.isAuxiliary());
+ assertEquals(mSubtypeOverridesImplicitlyEnabledSubtype,
+ mInputMethodSubtype.overridesImplicitlyEnabledSubtype());
+ assertEquals(mSubtypeId, mInputMethodSubtype.hashCode());
+ }
+
private void assertService(ServiceInfo expected, ServiceInfo actual) {
assertEquals(expected.getIconResource(), actual.getIconResource());
assertEquals(expected.labelRes, actual.labelRes);
@@ -110,19 +152,39 @@
assertEquals(expected.toString(), mInputMethodInfo.loadLabel(pm).toString());
}
- public void testWriteToParcel() {
- Parcel p = Parcel.obtain();
+ public void testInputMethodInfoWriteToParcel() {
+ final Parcel p = Parcel.obtain();
mInputMethodInfo.writeToParcel(p, 0);
p.setDataPosition(0);
- InputMethodInfo inputMethodInfo = InputMethodInfo.CREATOR.createFromParcel(p);
+ final InputMethodInfo imi = InputMethodInfo.CREATOR.createFromParcel(p);
- assertEquals(mInputMethodInfo.getPackageName(), inputMethodInfo.getPackageName());
- assertEquals(mInputMethodInfo.getServiceName(), inputMethodInfo.getServiceName());
- assertEquals(mInputMethodInfo.getSettingsActivity(), inputMethodInfo.getSettingsActivity());
- assertEquals(mInputMethodInfo.getId(), inputMethodInfo.getId());
- assertEquals(mInputMethodInfo.getIsDefaultResourceId(), inputMethodInfo
- .getIsDefaultResourceId());
- assertService(mInputMethodInfo.getServiceInfo(), inputMethodInfo.getServiceInfo());
+ assertEquals(mInputMethodInfo.getPackageName(), imi.getPackageName());
+ assertEquals(mInputMethodInfo.getServiceName(), imi.getServiceName());
+ assertEquals(mInputMethodInfo.getSettingsActivity(), imi.getSettingsActivity());
+ assertEquals(mInputMethodInfo.getId(), imi.getId());
+ assertEquals(mInputMethodInfo.getIsDefaultResourceId(), imi.getIsDefaultResourceId());
+ assertService(mInputMethodInfo.getServiceInfo(), imi.getServiceInfo());
+ }
+
+ public void testInputMethodSubtypeWriteToParcel() {
+ final Parcel p = Parcel.obtain();
+ mInputMethodSubtype.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ final InputMethodSubtype subtype = InputMethodSubtype.CREATOR.createFromParcel(p);
+
+ assertEquals(mInputMethodSubtype.containsExtraValueKey(mSubtypeExtraValue_key),
+ subtype.containsExtraValueKey(mSubtypeExtraValue_key));
+ assertEquals(mInputMethodSubtype.getExtraValue(), subtype.getExtraValue());
+ assertEquals(mInputMethodSubtype.getExtraValueOf(mSubtypeExtraValue_key),
+ subtype.getExtraValueOf(mSubtypeExtraValue_key));
+ assertEquals(mInputMethodSubtype.getIconResId(), subtype.getIconResId());
+ assertEquals(mInputMethodSubtype.getLocale(), subtype.getLocale());
+ assertEquals(mInputMethodSubtype.getMode(), subtype.getMode());
+ assertEquals(mInputMethodSubtype.getNameResId(), subtype.getNameResId());
+ assertEquals(mInputMethodSubtype.hashCode(), subtype.hashCode());
+ assertEquals(mInputMethodSubtype.isAuxiliary(), subtype.isAuxiliary());
+ assertEquals(mInputMethodSubtype.overridesImplicitlyEnabledSubtype(),
+ subtype.overridesImplicitlyEnabledSubtype());
}
class MockPrinter implements Printer {
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index 6674bdf..8fb2f15 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
@Option(name="cts-install-path", description="the path to the cts installation to use")
private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
- public static final String CTS_BUILD_VERSION = "4.2_r1";
+ public static final String CTS_BUILD_VERSION = "4.2_r2";
/**
* {@inheritDoc}