├── MODULE_LICENSE_APACHE2 ├── res ├── drawable-hdpi │ ├── zoom_slider.png │ ├── menu_popup.9.png │ ├── zoom_tickmark.png │ ├── focus_focused.9.png │ ├── focus_focusing.9.png │ ├── ic_menu_gallery.png │ ├── ic_menuselect_on.png │ ├── bg_camera_pattern.png │ ├── btn_ic_review_done.png │ ├── btn_ic_review_play.png │ ├── btn_shutter_normal.png │ ├── ic_launcher_camera.png │ ├── ic_menuselect_off.png │ ├── zoom_background.9.png │ ├── zoom_finetickmark.png │ ├── border_view_finder.9.png │ ├── btn_ic_camera_shutter.png │ ├── btn_ic_review_cancel.png │ ├── btn_ic_video_record.png │ ├── btn_mode_switch_bg.9.png │ ├── btn_shutter_pressed.png │ ├── focus_focus_failed.9.png │ ├── ic_menuselect_gps_off.png │ ├── ic_menuselect_gps_on.png │ ├── ic_menuselect_wb_auto.png │ ├── ic_viewfinder_gps_off.png │ ├── ic_viewfinder_gps_on.png │ ├── ic_viewfinder_wb_auto.png │ ├── menu_popup_triangle.png │ ├── ic_menuselect_flash_off.png │ ├── ic_menuselect_flash_on.png │ ├── ic_menuselect_wb_cloudy.png │ ├── ic_recording_indicator.png │ ├── ic_viewfinder_flash_off.png │ ├── ic_viewfinder_flash_on.png │ ├── ic_viewfinder_iconbar.9.png │ ├── ic_viewfinder_settings.png │ ├── ic_viewfinder_wb_cloudy.png │ ├── on_screen_hint_frame.9.png │ ├── btn_camera_review_normal.9.png │ ├── btn_ic_mode_switch_camera.png │ ├── btn_ic_mode_switch_video.png │ ├── btn_ic_review_retake_photo.png │ ├── btn_ic_review_retake_video.png │ ├── btn_ic_video_record_stop.png │ ├── ic_launcher_video_camera.png │ ├── ic_menu_camera_video_view.png │ ├── ic_menuselect_flash_auto.png │ ├── ic_menuselect_wb_daylight.png │ ├── ic_viewfinder_flash_auto.png │ ├── ic_viewfinder_wb_daylight.png │ ├── border_last_picture_normal.9.png │ ├── btn_camera_review_pressed.9.png │ ├── btn_mode_switch_knob_normal.png │ ├── btn_mode_switch_knob_pressed.png │ ├── ic_menuselect_wb_fluorescent.png │ ├── ic_viewfinder_gps_no_signal.png │ ├── ic_viewfinder_wb_fluorescent.png │ ├── scrollbar_handle_vertical.9.png │ ├── border_last_picture_pressed.9.png │ ├── btn_camera_review_highlight.9.png │ ├── ic_menuselect_wb_incandescent.png │ ├── ic_viewfinder_video_quality_hd.png │ ├── ic_viewfinder_video_quality_low.png │ ├── ic_viewfinder_video_quality_mms.png │ ├── ic_viewfinder_wb_incandescent.png │ ├── ic_menuselect_camera_facing_back.png │ ├── ic_menuselect_camera_facing_front.png │ ├── ic_viewfinder_camera_facing_back.png │ ├── ic_viewfinder_camera_facing_front.png │ ├── ic_viewfinder_video_quality_high.png │ ├── ic_viewfinder_video_quality_youtube.png │ └── ic_viewfinder_video_quality_youtubehd.png ├── drawable │ ├── camera_background.xml │ ├── btn_shutter.xml │ ├── border_last_picture.xml │ ├── btn_mode_switch_knob.xml │ └── btn_camera_review.xml ├── values-land │ └── dimens.xml ├── values │ ├── dimens.xml │ ├── colors.xml │ ├── config.xml │ ├── attrs.xml │ └── styles.xml ├── anim │ ├── on_screen_hint_enter.xml │ └── on_screen_hint_exit.xml ├── layout │ ├── on_screen_hint.xml │ ├── camera.xml │ ├── camera_control.xml │ ├── video_camera.xml │ └── attach_camera_control.xml └── xml │ └── video_preferences.xml ├── proguard.flags ├── Android.mk ├── tests ├── Android.mk ├── src │ └── com │ │ └── android │ │ └── camera │ │ ├── unittest │ │ └── CameraTest.java │ │ ├── UnitTests.java │ │ ├── CameraLaunchPerformance.java │ │ ├── StressTests.java │ │ ├── gallery │ │ ├── MockImageList.java │ │ ├── LruCacheUnitTests.java │ │ └── MockImage.java │ │ ├── CameraStressTestRunner.java │ │ ├── functional │ │ └── CameraTest.java │ │ ├── stress │ │ └── SwitchPreview.java │ │ └── power │ │ └── ImageAndVideoCapture.java └── AndroidManifest.xml ├── src └── com │ └── android │ └── camera │ ├── ui │ ├── GLOutOfMemoryException.java │ ├── ZoomControllerListener.java │ ├── Texture.java │ ├── ColorTexture.java │ ├── CanvasTexture.java │ ├── RawTexture.java │ ├── ResourceTexture.java │ ├── GpsIndicator.java │ ├── MeasureHelper.java │ ├── LinearLayout.java │ ├── BasicTexture.java │ ├── NinePatchChunk.java │ ├── NinePatchTexture.java │ ├── StringTexture.java │ ├── RotateRecordingTime.java │ ├── GLOptionHeader.java │ ├── RestoreSettingsItem.java │ ├── AbstractIndicator.java │ ├── CameraEGLConfigChooser.java │ ├── BitmapTexture.java │ ├── BasicIndicator.java │ ├── RotatePane.java │ ├── PreferenceAdapter.java │ └── CamcorderHeadUpDisplay.java │ ├── CameraHardwareException.java │ ├── NoSearchActivity.java │ ├── gallery │ ├── Image.java │ ├── IImage.java │ ├── IImageList.java │ ├── VideoObject.java │ ├── VideoList.java │ ├── LruCache.java │ ├── BaseImage.java │ └── ImageList.java │ ├── IntArray.java │ ├── RecordLocationPreference.java │ ├── CameraPreference.java │ ├── CameraButtonIntentReceiver.java │ ├── PreferenceGroup.java │ ├── IconIndicator.java │ ├── IconListPreference.java │ ├── PreviewFrameLayout.java │ ├── RotateImageView.java │ ├── PreferenceInflater.java │ ├── ListPreference.java │ ├── BitmapManager.java │ └── ShutterButton.java ├── CleanSpec.mk └── AndroidManifest.xml /MODULE_LICENSE_APACHE2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /res/drawable-hdpi/zoom_slider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/zoom_slider.png -------------------------------------------------------------------------------- /res/drawable-hdpi/menu_popup.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/menu_popup.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/zoom_tickmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/zoom_tickmark.png -------------------------------------------------------------------------------- /res/drawable-hdpi/focus_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/focus_focused.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/focus_focusing.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/focus_focusing.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menu_gallery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menu_gallery.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_on.png -------------------------------------------------------------------------------- /res/drawable-hdpi/bg_camera_pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/bg_camera_pattern.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_review_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_review_done.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_review_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_review_play.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_shutter_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_shutter_normal.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_launcher_camera.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_off.png -------------------------------------------------------------------------------- /res/drawable-hdpi/zoom_background.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/zoom_background.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/zoom_finetickmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/zoom_finetickmark.png -------------------------------------------------------------------------------- /res/drawable-hdpi/border_view_finder.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/border_view_finder.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_camera_shutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_camera_shutter.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_review_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_review_cancel.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_video_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_video_record.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_mode_switch_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_mode_switch_bg.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_shutter_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_shutter_pressed.png -------------------------------------------------------------------------------- /res/drawable-hdpi/focus_focus_failed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/focus_focus_failed.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_gps_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_gps_off.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_gps_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_gps_on.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_wb_auto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_wb_auto.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_gps_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_gps_off.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_gps_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_gps_on.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_wb_auto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_wb_auto.png -------------------------------------------------------------------------------- /res/drawable-hdpi/menu_popup_triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/menu_popup_triangle.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_flash_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_flash_off.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_flash_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_flash_on.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_wb_cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_wb_cloudy.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_recording_indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_recording_indicator.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_flash_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_flash_off.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_flash_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_flash_on.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_iconbar.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_iconbar.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_settings.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_wb_cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_wb_cloudy.png -------------------------------------------------------------------------------- /res/drawable-hdpi/on_screen_hint_frame.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/on_screen_hint_frame.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_camera_review_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_camera_review_normal.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_mode_switch_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_mode_switch_camera.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_mode_switch_video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_mode_switch_video.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_review_retake_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_review_retake_photo.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_review_retake_video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_review_retake_video.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_ic_video_record_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_ic_video_record_stop.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher_video_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_launcher_video_camera.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menu_camera_video_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menu_camera_video_view.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_flash_auto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_flash_auto.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_wb_daylight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_wb_daylight.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_flash_auto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_flash_auto.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_wb_daylight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_wb_daylight.png -------------------------------------------------------------------------------- /res/drawable-hdpi/border_last_picture_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/border_last_picture_normal.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_camera_review_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_camera_review_pressed.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_mode_switch_knob_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_mode_switch_knob_normal.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_mode_switch_knob_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_mode_switch_knob_pressed.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_wb_fluorescent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_wb_fluorescent.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_gps_no_signal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_gps_no_signal.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_wb_fluorescent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_wb_fluorescent.png -------------------------------------------------------------------------------- /res/drawable-hdpi/scrollbar_handle_vertical.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/scrollbar_handle_vertical.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/border_last_picture_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/border_last_picture_pressed.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/btn_camera_review_highlight.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/btn_camera_review_highlight.9.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_wb_incandescent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_wb_incandescent.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_video_quality_hd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_video_quality_hd.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_video_quality_low.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_video_quality_low.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_video_quality_mms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_video_quality_mms.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_wb_incandescent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_wb_incandescent.png -------------------------------------------------------------------------------- /proguard.flags: -------------------------------------------------------------------------------- 1 | # ctors of subclasses of CameraPreference are called with Java reflection. 2 | -keep class * extends com.android.camera.CameraPreference { 3 | (...); 4 | } 5 | -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_camera_facing_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_camera_facing_back.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_menuselect_camera_facing_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_menuselect_camera_facing_front.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_camera_facing_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_camera_facing_back.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_camera_facing_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_camera_facing_front.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_video_quality_high.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_video_quality_high.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_video_quality_youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_video_quality_youtube.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_viewfinder_video_quality_youtubehd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redux/android_packages_apps_Camera/master/res/drawable-hdpi/ic_viewfinder_video_quality_youtubehd.png -------------------------------------------------------------------------------- /res/drawable/camera_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | include $(CLEAR_VARS) 3 | 4 | LOCAL_MODULE_TAGS := optional 5 | 6 | LOCAL_SRC_FILES := $(call all-java-files-under, src) 7 | 8 | LOCAL_PACKAGE_NAME := Camera 9 | LOCAL_SDK_VERSION := current 10 | 11 | LOCAL_PROGUARD_FLAG_FILES := proguard.flags 12 | 13 | include $(BUILD_PACKAGE) 14 | 15 | # Use the following include to make our test apk. 16 | include $(call all-makefiles-under,$(LOCAL_PATH)) 17 | -------------------------------------------------------------------------------- /tests/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | include $(CLEAR_VARS) 3 | 4 | # We only want this apk build for tests. 5 | LOCAL_MODULE_TAGS := tests 6 | 7 | LOCAL_JAVA_LIBRARIES := android.test.runner 8 | 9 | # Include all test java files. 10 | LOCAL_SRC_FILES := $(call all-java-files-under, src) 11 | 12 | LOCAL_PACKAGE_NAME := CameraTests 13 | 14 | LOCAL_INSTRUMENTATION_FOR := Camera 15 | 16 | include $(BUILD_PACKAGE) 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/values-land/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/GLOutOfMemoryException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | public class GLOutOfMemoryException extends Exception { 20 | } 21 | -------------------------------------------------------------------------------- /res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 64dip 22 | 23 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/ZoomControllerListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | public interface ZoomControllerListener { 20 | public void onZoomChanged(int index, float ratio, boolean isMoving); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/Texture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | interface Texture { 20 | public void draw(GLRootView root, int x, int y); 21 | public void draw(GLRootView root, int x, int y, int w, int h); 22 | } 23 | -------------------------------------------------------------------------------- /res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | #FFFFFFFF 22 | #FFFF0033 23 | 24 | -------------------------------------------------------------------------------- /res/anim/on_screen_hint_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 24 | -------------------------------------------------------------------------------- /res/anim/on_screen_hint_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 24 | -------------------------------------------------------------------------------- /res/drawable/btn_shutter.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /res/drawable/border_last_picture.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /res/drawable/btn_mode_switch_knob.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/com/android/camera/CameraHardwareException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | /** 20 | * This class represents the condition that we cannot open the camera hardware 21 | * successfully. For example, another process is using the camera. 22 | */ 23 | public class CameraHardwareException extends Exception { 24 | 25 | public CameraHardwareException(Throwable t) { 26 | super(t); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/com/android/camera/NoSearchActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.app.Activity; 20 | 21 | /** 22 | * An activity which disables the search key function. 23 | * 24 | *

To use it, just inherit from {@code NoSearchActivity} instead of 25 | * {@code Activity}. 26 | */ 27 | public class NoSearchActivity extends Activity { 28 | @Override 29 | public boolean onSearchRequested() { 30 | return false; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/ColorTexture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | class ColorTexture implements Texture { 20 | 21 | private int mColor; 22 | 23 | public ColorTexture(int color) { 24 | mColor = color; 25 | } 26 | 27 | public void draw(GLRootView root, int x, int y) { 28 | } 29 | 30 | public void draw(GLRootView root, int x, int y, int w, int h) { 31 | root.drawColor(x, y, w, h, mColor); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/unittest/CameraTest.java: -------------------------------------------------------------------------------- 1 | package com.android.camera.unittest; 2 | 3 | import com.android.camera.Camera; 4 | 5 | import android.test.suitebuilder.annotation.SmallTest; 6 | 7 | import junit.framework.TestCase; 8 | 9 | @SmallTest 10 | public class CameraTest extends TestCase { 11 | public void testRoundOrientation() { 12 | assertEquals(0, Camera.roundOrientation(0)); 13 | assertEquals(0, Camera.roundOrientation(0 + 44)); 14 | assertEquals(90, Camera.roundOrientation(0 + 45)); 15 | assertEquals(90, Camera.roundOrientation(90)); 16 | assertEquals(90, Camera.roundOrientation(90 + 44)); 17 | assertEquals(180, Camera.roundOrientation(90 + 45)); 18 | assertEquals(180, Camera.roundOrientation(180)); 19 | assertEquals(180, Camera.roundOrientation(180 + 44)); 20 | assertEquals(270, Camera.roundOrientation(180 + 45)); 21 | assertEquals(270, Camera.roundOrientation(270)); 22 | assertEquals(270, Camera.roundOrientation(270 + 44)); 23 | assertEquals(0, Camera.roundOrientation(270 + 45)); 24 | assertEquals(0, Camera.roundOrientation(359)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /res/drawable/btn_camera_review.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/UnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.test.suitebuilder.UnitTestSuiteBuilder; 20 | 21 | import junit.framework.Test; 22 | import junit.framework.TestSuite; 23 | 24 | /** 25 | * TestSuite for all Camera unit tests. 26 | */ 27 | public class UnitTests extends TestSuite { 28 | 29 | public static Test suite() { 30 | return new UnitTestSuiteBuilder(UnitTests.class) 31 | .includePackages("com.android.camera.unittest", 32 | "com.android.camera.gallery") 33 | .named("Camera Unit Tests") 34 | .build(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /res/values/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 22 | 23 | 25 | false 26 | 27 | 28 | true 29 | true 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/com/android/camera/gallery/Image.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.gallery; 18 | 19 | import android.content.ContentResolver; 20 | import android.net.Uri; 21 | 22 | /** 23 | * The class for normal images in gallery. 24 | */ 25 | public class Image extends BaseImage implements IImage { 26 | private final int mRotation; 27 | 28 | public Image(ContentResolver cr, 29 | long id, Uri uri, long miniThumbMagic, 30 | long dateTaken, 31 | int rotation) { 32 | super(cr, id, uri, miniThumbMagic, 33 | dateTaken); 34 | mRotation = rotation; 35 | } 36 | 37 | @Override 38 | public int getDegreesRotated() { 39 | return mRotation; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /res/layout/on_screen_hint.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 25 | 26 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/com/android/camera/IntArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | public class IntArray { 20 | private static final int INIT_CAPACITY = 8; 21 | 22 | private int mData[] = new int[INIT_CAPACITY]; 23 | private int mSize = 0; 24 | 25 | public void add(int value) { 26 | if (mData.length == mSize) { 27 | int temp[] = new int[mSize + mSize]; 28 | System.arraycopy(mData, 0, temp, 0, mSize); 29 | mData = temp; 30 | } 31 | mData[mSize++] = value; 32 | } 33 | 34 | public int size() { 35 | return mSize; 36 | } 37 | 38 | public int[] toArray(int[] result) { 39 | if (result == null || result.length < mSize) { 40 | result = new int[mSize]; 41 | } 42 | System.arraycopy(mData, 0, result, 0, mSize); 43 | return result; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/com/android/camera/gallery/IImage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.gallery; 18 | 19 | import android.graphics.Bitmap; 20 | import android.net.Uri; 21 | 22 | /** 23 | * The interface of all images used in gallery. 24 | */ 25 | public interface IImage { 26 | static final int THUMBNAIL_TARGET_SIZE = 320; 27 | static final int MINI_THUMB_TARGET_SIZE = 96; 28 | static final int THUMBNAIL_MAX_NUM_PIXELS = 512 * 384; 29 | static final int MINI_THUMB_MAX_NUM_PIXELS = 128 * 128; 30 | static final int UNCONSTRAINED = -1; 31 | 32 | public static final boolean ROTATE_AS_NEEDED = true; 33 | public static final boolean NO_ROTATE = false; 34 | 35 | public abstract Uri fullSizeImageUri(); 36 | 37 | // Get metadata of the image 38 | public abstract long getDateTaken(); 39 | 40 | // Get the bitmap of the mini thumbnail. 41 | public abstract Bitmap miniThumbBitmap(); 42 | } 43 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/CanvasTexture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.graphics.Bitmap; 20 | import android.graphics.Canvas; 21 | import android.graphics.Bitmap.Config; 22 | 23 | /** Using a canvas to draw the texture */ 24 | abstract class CanvasTexture extends BitmapTexture { 25 | protected Canvas mCanvas; 26 | 27 | public CanvasTexture(int width, int height) { 28 | setSize(width, height); 29 | } 30 | 31 | @Override 32 | protected Bitmap getBitmap() { 33 | Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888); 34 | mCanvas = new Canvas(bitmap); 35 | onDraw(mCanvas, bitmap); 36 | return bitmap; 37 | } 38 | 39 | @Override 40 | protected void freeBitmap(Bitmap bitmap) { 41 | bitmap.recycle(); 42 | } 43 | 44 | abstract protected void onDraw(Canvas canvas, Bitmap backing); 45 | } 46 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/CameraLaunchPerformance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.app.Activity; 20 | import android.os.Bundle; 21 | import android.test.LaunchPerformanceBase; 22 | 23 | /** 24 | * Instrumentation class for Camera launch performance testing. 25 | */ 26 | public class CameraLaunchPerformance extends LaunchPerformanceBase { 27 | @SuppressWarnings("unused") 28 | private static final String TAG = "CameraLaunchPerformance"; 29 | 30 | @Override 31 | public void onCreate(Bundle arguments) { 32 | super.onCreate(arguments); 33 | mIntent.setClassName(getTargetContext(), "com.android.camera.Camera"); 34 | start(); 35 | } 36 | 37 | /** 38 | * Calls LaunchApp and finish. 39 | */ 40 | @Override 41 | public void onStart() { 42 | super.onStart(); 43 | LaunchApp(); 44 | finish(Activity.RESULT_OK, mResults); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 32 | 33 | 34 | 37 | 38 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/StressTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import com.android.camera.stress.ImageCapture; 20 | import com.android.camera.stress.SwitchPreview; 21 | import com.android.camera.stress.CameraLatency; 22 | import com.android.camera.stress.CameraStartUp; 23 | 24 | import junit.framework.Test; 25 | import junit.framework.TestSuite; 26 | 27 | 28 | /** 29 | * Instrumentation Test Runner for all Camera tests. 30 | * 31 | * Running all tests: 32 | * 33 | * adb shell am instrument -w \ 34 | * com.android.camera.tests/com.android.camera.CameraStressTestRunner 35 | */ 36 | 37 | public class StressTests extends TestSuite { 38 | public static Test suite() { 39 | TestSuite result = new TestSuite(); 40 | result.addTestSuite(SwitchPreview.class); 41 | result.addTestSuite(ImageCapture.class); 42 | result.addTestSuite(CameraLatency.class); 43 | result.addTestSuite(CameraStartUp.class); 44 | return result; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/gallery/MockImageList.java: -------------------------------------------------------------------------------- 1 | package com.android.camera.gallery; 2 | 3 | import android.content.ContentResolver; 4 | import android.net.Uri; 5 | import android.os.Parcel; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | 10 | public class MockImageList implements IImageList { 11 | 12 | private final ArrayList mList = new ArrayList(); 13 | 14 | public void checkThumbnail(int index) { 15 | } 16 | 17 | public void deactivate() { 18 | } 19 | 20 | public HashMap getBucketIds() { 21 | return null; 22 | } 23 | 24 | public int getCount() { 25 | return mList.size(); 26 | } 27 | 28 | public IImage getImageAt(int i) { 29 | return mList.get(i); 30 | } 31 | 32 | public IImage getImageForUri(Uri uri) { 33 | return null; 34 | } 35 | 36 | public int getImageIndex(IImage image) { 37 | return mList.indexOf(image); 38 | } 39 | 40 | public boolean isEmpty() { 41 | return mList.isEmpty(); 42 | } 43 | 44 | public boolean removeImage(IImage image) { 45 | return mList.remove(image); 46 | } 47 | 48 | public boolean removeImageAt(int i) { 49 | return mList.remove(i) != null; 50 | } 51 | 52 | public void addImage(MockImage image) { 53 | mList.add(image); 54 | image.setContainer(this); 55 | } 56 | 57 | public void open(ContentResolver resolver) { 58 | } 59 | 60 | public void close() { 61 | } 62 | 63 | public void writeToParcel(Parcel out, int flags) { 64 | throw new UnsupportedOperationException(); 65 | } 66 | 67 | public int describeContents() { 68 | return 0; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/RawTexture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | 20 | import javax.microedition.khronos.opengles.GL11; 21 | 22 | class RawTexture extends BasicTexture { 23 | 24 | private RawTexture(GL11 gl, int id) { 25 | super(gl, id, STATE_LOADED); 26 | } 27 | 28 | public GL11 getBoundGL() { 29 | return mGL; 30 | } 31 | 32 | public static RawTexture newInstance(GL11 gl) { 33 | int[] textureId = new int[1]; 34 | gl.glGenTextures(1, textureId, 0); 35 | int glError = gl.glGetError(); 36 | if (glError != GL11.GL_NO_ERROR) { 37 | throw new RuntimeException("GL_ERROR: " + glError); 38 | } 39 | return new RawTexture(gl, textureId[0]); 40 | } 41 | 42 | @Override 43 | protected boolean bind(GLRootView glRootView, GL11 gl) { 44 | if (mGL == gl) { 45 | gl.glBindTexture(GL11.GL_TEXTURE_2D, getId()); 46 | return true; 47 | } 48 | return false; 49 | } 50 | 51 | public void drawBack(GLRootView root, int x, int y, int w, int h) { 52 | root.drawTexture(this, x, y, w, h, 1f); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/ResourceTexture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import com.android.camera.Util; 20 | 21 | import android.content.Context; 22 | import android.graphics.Bitmap; 23 | import android.graphics.BitmapFactory; 24 | 25 | class ResourceTexture extends BitmapTexture { 26 | 27 | protected final Context mContext; 28 | protected final int mResId; 29 | protected Bitmap mBitmap; 30 | 31 | public ResourceTexture(Context context, int resId) { 32 | mContext = Util.checkNotNull(context); 33 | mResId = resId; 34 | } 35 | 36 | @Override 37 | protected Bitmap getBitmap() { 38 | if (mBitmap != null) return mBitmap; 39 | BitmapFactory.Options options = new BitmapFactory.Options(); 40 | options.inPreferredConfig = Bitmap.Config.ARGB_8888; 41 | mBitmap = BitmapFactory.decodeResource( 42 | mContext.getResources(), mResId, options); 43 | setSize(mBitmap.getWidth(), mBitmap.getHeight()); 44 | return mBitmap; 45 | } 46 | 47 | @Override 48 | protected void freeBitmap(Bitmap bitmap) { 49 | Util.Assert(bitmap == mBitmap); 50 | bitmap.recycle(); 51 | mBitmap = null; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/android/camera/gallery/IImageList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.gallery; 18 | 19 | // 20 | // ImageList and Image classes have one-to-one correspondence. 21 | // The class hierarchy (* = abstract class): 22 | // 23 | // IImageList 24 | // - BaseImageList (*) 25 | // - VideoList 26 | // - ImageList 27 | // - DrmImageList 28 | // - SingleImageList (contains UriImage) 29 | // - ImageListUber 30 | // 31 | // IImage 32 | // - BaseImage (*) 33 | // - VideoObject 34 | // - Image 35 | // - DrmImage 36 | // - UriImage 37 | // 38 | 39 | /** 40 | * The interface of all image collections used in gallery. 41 | */ 42 | public interface IImageList { 43 | 44 | /** 45 | * Returns the count of image objects. 46 | * 47 | * @return the number of images 48 | */ 49 | public int getCount(); 50 | 51 | /** 52 | * Returns the image at the ith position. 53 | * 54 | * @param i the position 55 | * @return the image at the ith position 56 | */ 57 | public IImage getImageAt(int i); 58 | 59 | /** 60 | * Closes this list to release resources, no further operation is allowed. 61 | */ 62 | public void close(); 63 | } 64 | -------------------------------------------------------------------------------- /src/com/android/camera/RecordLocationPreference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.content.ContentResolver; 20 | import android.content.Context; 21 | import android.content.SharedPreferences; 22 | import android.util.AttributeSet; 23 | 24 | /** 25 | * {@code RecordLocationPreference} is used to keep the "store locaiton" 26 | * option in {@code SharedPreference}. 27 | */ 28 | public class RecordLocationPreference extends IconListPreference { 29 | 30 | public static final String KEY = "pref_camera_recordlocation_key"; 31 | 32 | public static final String VALUE_NONE = "none"; 33 | public static final String VALUE_ON = "on"; 34 | public static final String VALUE_OFF = "off"; 35 | 36 | private final ContentResolver mResolver; 37 | 38 | public RecordLocationPreference(Context context, AttributeSet attrs) { 39 | super(context, attrs); 40 | mResolver = context.getContentResolver(); 41 | } 42 | 43 | @Override 44 | public String getValue() { 45 | return get(getSharedPreferences(), mResolver) ? VALUE_ON : VALUE_OFF; 46 | } 47 | 48 | public static boolean get( 49 | SharedPreferences pref, ContentResolver resolver) { 50 | String value = pref.getString(KEY, VALUE_NONE); 51 | return VALUE_ON.equals(value); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/android/camera/CameraPreference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.content.Context; 20 | import android.content.SharedPreferences; 21 | import android.content.res.TypedArray; 22 | import android.util.AttributeSet; 23 | 24 | import com.android.camera.R; 25 | 26 | /** 27 | * The base class of all Preferences used in Camera. The preferences can be 28 | * loaded from XML resource by PreferenceInflater. 29 | */ 30 | public abstract class CameraPreference { 31 | 32 | private final String mTitle; 33 | private SharedPreferences mSharedPreferences; 34 | private final Context mContext; 35 | 36 | public CameraPreference(Context context, AttributeSet attrs) { 37 | mContext = context; 38 | TypedArray a = context.obtainStyledAttributes( 39 | attrs, R.styleable.CameraPreference, 0, 0); 40 | mTitle = a.getString(R.styleable.CameraPreference_title); 41 | a.recycle(); 42 | } 43 | 44 | public String getTitle() { 45 | return mTitle; 46 | } 47 | 48 | public SharedPreferences getSharedPreferences() { 49 | if (mSharedPreferences == null) { 50 | mSharedPreferences = ComboPreferences.get(mContext); 51 | } 52 | return mSharedPreferences; 53 | } 54 | 55 | public abstract void reloadValue(); 56 | } 57 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/GpsIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.content.Context; 20 | 21 | import com.android.camera.R; 22 | import com.android.camera.IconListPreference; 23 | 24 | class GpsIndicator extends BasicIndicator { 25 | 26 | private static final int GPS_ON_INDEX = 1; 27 | 28 | private ResourceTexture mNoSignalIcon; 29 | private boolean mHasSignal = false; 30 | 31 | public GpsIndicator(Context context, IconListPreference preference) { 32 | super(context, preference); 33 | } 34 | 35 | @Override 36 | protected ResourceTexture getIcon() { 37 | if (mIndex == GPS_ON_INDEX && !mHasSignal) { 38 | if (mNoSignalIcon == null) { 39 | Context context = getGLRootView().getContext(); 40 | mNoSignalIcon = new ResourceTexture( 41 | context, R.drawable.ic_viewfinder_gps_no_signal); 42 | } 43 | return mNoSignalIcon; 44 | } 45 | return super.getIcon(); 46 | } 47 | 48 | public void setHasSignal(boolean hasSignal) { 49 | if (mHasSignal == hasSignal) return; 50 | mHasSignal = hasSignal; 51 | invalidate(); 52 | } 53 | 54 | @Override 55 | protected void onPreferenceChanged(int newIndex) { 56 | mHasSignal = false; 57 | super.onPreferenceChanged(newIndex); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/MeasureHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.graphics.Rect; 20 | import android.view.View.MeasureSpec; 21 | 22 | class MeasureHelper { 23 | 24 | private final GLView mComponent; 25 | private int mPreferredWidth; 26 | private int mPreferredHeight; 27 | 28 | public MeasureHelper(GLView component) { 29 | mComponent = component; 30 | } 31 | 32 | public MeasureHelper setPreferredContentSize(int width, int height) { 33 | mPreferredWidth = width; 34 | mPreferredHeight = height; 35 | return this; 36 | } 37 | 38 | public void measure(int widthSpec, int heightSpec) { 39 | Rect p = mComponent.getPaddings(); 40 | setMeasuredSize( 41 | getLength(widthSpec, mPreferredWidth + p.left + p.right), 42 | getLength(heightSpec, mPreferredHeight + p.top + p.bottom)); 43 | } 44 | 45 | private static int getLength(int measureSpec, int prefered) { 46 | int specLength = MeasureSpec.getSize(measureSpec); 47 | switch(MeasureSpec.getMode(measureSpec)) { 48 | case MeasureSpec.EXACTLY: return specLength; 49 | case MeasureSpec.AT_MOST: return Math.min(prefered, specLength); 50 | default: return prefered; 51 | } 52 | } 53 | 54 | protected void setMeasuredSize(int width, int height) { 55 | mComponent.setMeasuredSize(width, height); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/com/android/camera/CameraButtonIntentReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.content.BroadcastReceiver; 20 | import android.content.Context; 21 | import android.content.Intent; 22 | 23 | /** 24 | * {@code CameraButtonIntentReceiver} is invoked when the camera button is 25 | * long-pressed. 26 | * 27 | * It is declared in {@code AndroidManifest.xml} to receive the 28 | * {@code android.intent.action.CAMERA_BUTTON} intent. 29 | * 30 | * After making sure we can use the camera hardware, it starts the Camera 31 | * activity. 32 | */ 33 | public class CameraButtonIntentReceiver extends BroadcastReceiver { 34 | 35 | @Override 36 | public void onReceive(Context context, Intent intent) { 37 | // Try to get the camera hardware 38 | CameraHolder holder = CameraHolder.instance(); 39 | ComboPreferences pref = new ComboPreferences(context); 40 | int cameraId = CameraSettings.readPreferredCameraId(pref); 41 | if (holder.tryOpen(cameraId) == null) return; 42 | 43 | // We are going to launch the camera, so hold the camera for later use 44 | holder.keep(); 45 | holder.release(); 46 | Intent i = new Intent(Intent.ACTION_MAIN); 47 | i.setClass(context, Camera.class); 48 | i.addCategory(Intent.CATEGORY_LAUNCHER); 49 | i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 50 | | Intent.FLAG_ACTIVITY_CLEAR_TOP); 51 | context.startActivity(i); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/LinearLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.graphics.Rect; 20 | import android.view.View.MeasureSpec; 21 | 22 | class LinearLayout extends GLView { 23 | 24 | @Override 25 | protected void onMeasure(int widthSpec, int heightSpec) { 26 | int width = 0; 27 | int height = 0; 28 | for (int i = 0, n = getComponentCount(); i < n; ++i) { 29 | GLView view = getComponent(i); 30 | view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 31 | width = Math.max(width, view.getMeasuredWidth()); 32 | height += view.getMeasuredHeight(); 33 | } 34 | new MeasureHelper(this) 35 | .setPreferredContentSize(width, height) 36 | .measure(widthSpec, heightSpec); 37 | } 38 | 39 | @Override 40 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 41 | Rect p = mPaddings; 42 | int offsetX = p.left; 43 | int width = (r - l) - p.left - p.right; 44 | int offsetY = p.top; 45 | for (int i = 0, n = getComponentCount(); i < n; ++i) { 46 | GLView view = getComponent(i); 47 | view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 48 | int nextOffsetY = offsetY + view.getMeasuredHeight(); 49 | view.layout(offsetX, offsetY, offsetX + width, nextOffsetY); 50 | offsetY = nextOffsetY; 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/BasicTexture.java: -------------------------------------------------------------------------------- 1 | package com.android.camera.ui; 2 | 3 | import javax.microedition.khronos.opengles.GL11; 4 | 5 | abstract class BasicTexture implements Texture { 6 | 7 | protected static final int UNSPECIFIED = -1; 8 | 9 | public static final int STATE_UNLOADED = 0; 10 | public static final int STATE_LOADED = 1; 11 | public static final int STATE_ERROR = -1; 12 | 13 | protected GL11 mGL; 14 | 15 | protected int mId; 16 | protected int mState; 17 | 18 | protected int mWidth = UNSPECIFIED; 19 | protected int mHeight = UNSPECIFIED; 20 | 21 | protected int mTextureWidth; 22 | protected int mTextureHeight; 23 | 24 | protected BasicTexture(GL11 gl, int id, int state) { 25 | mGL = gl; 26 | mId = id; 27 | mState = state; 28 | } 29 | 30 | protected BasicTexture() { 31 | this(null, 0, STATE_UNLOADED); 32 | } 33 | 34 | protected void setSize(int width, int height) { 35 | mWidth = width; 36 | mHeight = height; 37 | } 38 | 39 | /** 40 | * Sets the size of the texture. Due to the limit of OpenGL, the texture 41 | * size must be of power of 2, the size of the content may not be the size 42 | * of the texture. 43 | */ 44 | protected void setTextureSize(int width, int height) { 45 | mTextureWidth = width; 46 | mTextureHeight = height; 47 | } 48 | 49 | public int getId() { 50 | return mId; 51 | } 52 | 53 | public int getWidth() { 54 | return mWidth; 55 | } 56 | 57 | public int getHeight() { 58 | return mHeight; 59 | } 60 | 61 | public void deleteFromGL() { 62 | if (mState == STATE_LOADED) { 63 | mGL.glDeleteTextures(1, new int[]{mId}, 0); 64 | } 65 | mState = STATE_UNLOADED; 66 | } 67 | 68 | public void draw(GLRootView root, int x, int y) { 69 | root.drawTexture(this, x, y, mWidth, mHeight); 70 | } 71 | 72 | public void draw(GLRootView root, int x, int y, int w, int h) { 73 | root.drawTexture(this, x, y, w, h); 74 | } 75 | 76 | abstract protected boolean bind(GLRootView root, GL11 gl); 77 | } 78 | -------------------------------------------------------------------------------- /res/layout/camera.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 24 | 29 | 33 | 36 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/NinePatchChunk.java: -------------------------------------------------------------------------------- 1 | package com.android.camera.ui; 2 | 3 | import android.graphics.Rect; 4 | 5 | import java.nio.ByteBuffer; 6 | import java.nio.ByteOrder; 7 | 8 | // See "frameworks/base/include/utils/ResourceTypes.h" for the format of 9 | // NinePatch chunk. 10 | class NinePatchChunk { 11 | 12 | public static final int NO_COLOR = 0x00000001; 13 | public static final int TRANSPARENT_COLOR = 0x00000000; 14 | 15 | public Rect mPaddings = new Rect(); 16 | 17 | public int mDivX[]; 18 | public int mDivY[]; 19 | public int mColor[]; 20 | 21 | private static void readIntArray(int[] data, ByteBuffer buffer) { 22 | for (int i = 0, n = data.length; i < n; ++i) { 23 | data[i] = buffer.getInt(); 24 | } 25 | } 26 | 27 | private static void checkDivCount(int length) { 28 | if (length == 0 || (length & 0x01) != 0) { 29 | throw new RuntimeException("invalid nine-patch: " + length); 30 | } 31 | } 32 | 33 | public static NinePatchChunk deserialize(byte[] data) { 34 | ByteBuffer byteBuffer = 35 | ByteBuffer.wrap(data).order(ByteOrder.nativeOrder()); 36 | 37 | byte wasSerialized = byteBuffer.get(); 38 | if (wasSerialized == 0) return null; 39 | 40 | NinePatchChunk chunk = new NinePatchChunk(); 41 | chunk.mDivX = new int[byteBuffer.get()]; 42 | chunk.mDivY = new int[byteBuffer.get()]; 43 | chunk.mColor = new int[byteBuffer.get()]; 44 | 45 | checkDivCount(chunk.mDivX.length); 46 | checkDivCount(chunk.mDivY.length); 47 | 48 | // skip 8 bytes 49 | byteBuffer.getInt(); 50 | byteBuffer.getInt(); 51 | 52 | chunk.mPaddings.left = byteBuffer.getInt(); 53 | chunk.mPaddings.right = byteBuffer.getInt(); 54 | chunk.mPaddings.top = byteBuffer.getInt(); 55 | chunk.mPaddings.bottom = byteBuffer.getInt(); 56 | 57 | // skip 4 bytes 58 | byteBuffer.getInt(); 59 | 60 | readIntArray(chunk.mDivX, byteBuffer); 61 | readIntArray(chunk.mDivY, byteBuffer); 62 | readIntArray(chunk.mColor, byteBuffer); 63 | 64 | return chunk; 65 | } 66 | } -------------------------------------------------------------------------------- /src/com/android/camera/ui/NinePatchTexture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.content.Context; 20 | import android.graphics.Bitmap; 21 | import android.graphics.BitmapFactory; 22 | import android.graphics.Rect; 23 | 24 | class NinePatchTexture extends ResourceTexture { 25 | private NinePatchChunk mChunk; 26 | 27 | public NinePatchTexture(Context context, int resId) { 28 | super(context, resId); 29 | } 30 | 31 | @Override 32 | protected Bitmap getBitmap() { 33 | if (mBitmap != null) return mBitmap; 34 | 35 | BitmapFactory.Options options = new BitmapFactory.Options(); 36 | options.inPreferredConfig = Bitmap.Config.ARGB_8888; 37 | Bitmap bitmap = BitmapFactory.decodeResource( 38 | mContext.getResources(), mResId, options); 39 | mBitmap = bitmap; 40 | setSize(bitmap.getWidth(), bitmap.getHeight()); 41 | mChunk = NinePatchChunk.deserialize(bitmap.getNinePatchChunk()); 42 | if (mChunk == null) { 43 | throw new RuntimeException("invalid nine-patch image: " + mResId); 44 | } 45 | return bitmap; 46 | } 47 | 48 | public Rect getPaddings() { 49 | // get the paddings from nine patch 50 | if (mChunk == null) getBitmap(); 51 | return mChunk.mPaddings; 52 | } 53 | 54 | public NinePatchChunk getNinePatchChunk() { 55 | if (mChunk == null) getBitmap(); 56 | return mChunk; 57 | } 58 | 59 | @Override 60 | public void draw(GLRootView root, int x, int y, int w, int h) { 61 | root.drawNinePatch(this, x, y, w, h); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/StringTexture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.graphics.Bitmap; 20 | import android.graphics.Canvas; 21 | import android.graphics.Paint; 22 | import android.graphics.Paint.FontMetricsInt; 23 | 24 | class StringTexture extends CanvasTexture { 25 | private static int DEFAULT_PADDING = 1; 26 | 27 | private final String mText; 28 | private final Paint mPaint; 29 | private final FontMetricsInt mMetrics; 30 | 31 | public StringTexture(String text, Paint paint, 32 | FontMetricsInt metrics, int width, int height) { 33 | super(width, height); 34 | mText = text; 35 | mPaint = paint; 36 | mMetrics = metrics; 37 | } 38 | 39 | 40 | public static StringTexture newInstance(String text, Paint paint) { 41 | FontMetricsInt metrics = paint.getFontMetricsInt(); 42 | int width = (int) (.5f + paint.measureText(text)) + DEFAULT_PADDING * 2; 43 | int height = metrics.bottom - metrics.top + DEFAULT_PADDING * 2; 44 | return new StringTexture(text, paint, metrics, width, height); 45 | } 46 | 47 | public static StringTexture newInstance( 48 | String text, float textSize, int color) { 49 | Paint paint = new Paint(); 50 | paint.setTextSize(textSize); 51 | paint.setAntiAlias(true); 52 | paint.setColor(color); 53 | 54 | return newInstance(text, paint); 55 | } 56 | 57 | @Override 58 | protected void onDraw(Canvas canvas, Bitmap backing) { 59 | canvas.translate(DEFAULT_PADDING, DEFAULT_PADDING - mMetrics.ascent); 60 | canvas.drawText(mText, 0, 0, mPaint); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/CameraStressTestRunner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.stress; 18 | 19 | 20 | import android.os.Bundle; 21 | import android.test.InstrumentationTestRunner; 22 | import android.test.InstrumentationTestSuite; 23 | import android.util.Log; 24 | import junit.framework.TestSuite; 25 | 26 | public class CameraStressTestRunner extends InstrumentationTestRunner { 27 | 28 | // Default recorder settings 29 | public static int mVideoDuration = 20000; // set default to 20 seconds 30 | public static int mVideoIterations = 100; // set default to 100 videos 31 | public static int mImageIterations = 100; // set default to 100 images 32 | 33 | @Override 34 | public TestSuite getAllTests() { 35 | TestSuite suite = new InstrumentationTestSuite(this); 36 | suite.addTestSuite(ImageCapture.class); 37 | return suite; 38 | } 39 | 40 | @Override 41 | public ClassLoader getLoader() { 42 | return CameraStressTestRunner.class.getClassLoader(); 43 | } 44 | 45 | @Override 46 | public void onCreate(Bundle icicle) { 47 | super.onCreate(icicle); 48 | String video_iterations = (String) icicle.get("video_iterations"); 49 | String image_iterations = (String) icicle.get("image_iterations"); 50 | String video_duration = (String) icicle.get("video_duration"); 51 | 52 | if ( video_iterations != null ) { 53 | mVideoIterations = Integer.parseInt(video_iterations); 54 | } 55 | if ( image_iterations != null) { 56 | mImageIterations = Integer.parseInt(image_iterations); 57 | } 58 | if ( video_duration != null) { 59 | mVideoDuration = Integer.parseInt(video_duration); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /CleanSpec.mk: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007 The Android Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | 16 | # If you don't need to do a full clean build but would like to touch 17 | # a file or delete some intermediate files, add a clean step to the end 18 | # of the list. These steps will only be run once, if they haven't been 19 | # run before. 20 | # 21 | # E.g.: 22 | # $(call add-clean-step, touch -c external/sqlite/sqlite3.h) 23 | # $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) 24 | # 25 | # Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with 26 | # files that are missing or have been moved. 27 | # 28 | # Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. 29 | # Use $(OUT_DIR) to refer to the "out" directory. 30 | # 31 | # If you need to re-do something that's already mentioned, just copy 32 | # the command and add it to the bottom of the list. E.g., if a change 33 | # that you made last week required touching a file and a change you 34 | # made today requires touching the same file, just copy the old 35 | # touch step and add it to the end of the list. 36 | # 37 | # ************************************************ 38 | # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST 39 | # ************************************************ 40 | 41 | # For example: 42 | #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) 43 | #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) 44 | #$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) 45 | #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) 46 | $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/Camera*) 47 | $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Camera*) 48 | 49 | # ************************************************ 50 | # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST 51 | # ************************************************ 52 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/RotateRecordingTime.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.util.Log; 22 | import android.graphics.Canvas; 23 | import android.view.ViewGroup; 24 | import android.widget.FrameLayout; 25 | import android.widget.TextView; 26 | 27 | import com.android.camera.R; 28 | 29 | // This is a rectangle that contains recording text view. Canvas is rotated 30 | // before passing to recording text. 31 | public class RotateRecordingTime extends FrameLayout { 32 | private static final String TAG = "RotateRecordingTime"; 33 | private float mTextSize; 34 | private int mOrientation; 35 | 36 | public RotateRecordingTime(Context context, AttributeSet attrs) { 37 | super(context, attrs); 38 | } 39 | 40 | @Override 41 | protected void onFinishInflate() { 42 | TextView v = (TextView) findViewById(R.id.recording_time); 43 | mTextSize = (float) v.getTextSize(); 44 | } 45 | 46 | // degrees in counter-clockwise 47 | public void setOrientation(int degrees) { 48 | if (degrees % 90 == 0) { 49 | mOrientation = degrees % 360; 50 | if (mOrientation < 0) mOrientation += 360; 51 | } else { 52 | Log.e(TAG, "Invalid orientation=" + degrees); 53 | } 54 | } 55 | 56 | @Override 57 | protected void dispatchDraw(Canvas canvas) { 58 | canvas.save(); 59 | float width = (float) getWidth(); 60 | float height = (float) getHeight(); 61 | if (mOrientation == 0 || mOrientation == 180) { 62 | canvas.translate(0, height / 2 - mTextSize / 2); 63 | } else { 64 | canvas.translate(-width / 2 + mTextSize / 2, 0); 65 | } 66 | // Rotate the canvas in the opposite direction to compensate. 67 | canvas.rotate(-mOrientation, width / 2, height / 2); 68 | super.dispatchDraw(canvas); 69 | canvas.restore(); 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /src/com/android/camera/gallery/VideoObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.gallery; 18 | 19 | import com.android.camera.BitmapManager; 20 | 21 | import android.content.ContentResolver; 22 | import android.graphics.Bitmap; 23 | import android.net.Uri; 24 | import android.provider.MediaStore.Images; 25 | import android.util.Log; 26 | 27 | /** 28 | * Represents a particular video and provides access to the underlying data and 29 | * two thumbnail bitmaps as well as other information such as the id, and the 30 | * path to the actual video data. 31 | */ 32 | public class VideoObject extends BaseImage implements IImage { 33 | private static final String TAG = "VideoObject"; 34 | /** 35 | * Constructor. 36 | * 37 | * @param id the image id of the image 38 | * @param cr the content resolver 39 | */ 40 | protected VideoObject(ContentResolver cr, 41 | long id, Uri uri, long miniThumbMagic, 42 | long dateTaken) { 43 | super(cr, id, uri, miniThumbMagic, 44 | dateTaken); 45 | } 46 | 47 | @Override 48 | public boolean equals(Object other) { 49 | if (other == null || !(other instanceof VideoObject)) return false; 50 | return fullSizeImageUri().equals( 51 | ((VideoObject) other).fullSizeImageUri()); 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | return fullSizeImageUri().toString().hashCode(); 57 | } 58 | 59 | @Override 60 | public Bitmap miniThumbBitmap() { 61 | try { 62 | long id = mId; 63 | return BitmapManager.instance().getThumbnail(mContentResolver, 64 | id, Images.Thumbnails.MICRO_KIND, null, true); 65 | } catch (Throwable ex) { 66 | Log.e(TAG, "miniThumbBitmap got exception", ex); 67 | return null; 68 | } 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return new StringBuilder("VideoObject").append(mId).toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/gallery/LruCacheUnitTests.java: -------------------------------------------------------------------------------- 1 | package com.android.camera.gallery; 2 | 3 | import android.test.AndroidTestCase; 4 | import android.test.suitebuilder.annotation.SmallTest; 5 | import android.util.Log; 6 | 7 | public class LruCacheUnitTests extends AndroidTestCase { 8 | 9 | @SmallTest 10 | public void testPut() { 11 | LruCache cache = new LruCache(2); 12 | Integer key = Integer.valueOf(1); 13 | Integer value = Integer.valueOf(3); 14 | cache.put(key, value); 15 | assertEquals(value, cache.get(key)); 16 | } 17 | 18 | @SmallTest 19 | public void testTracingInUsedObject() { 20 | LruCache cache = new LruCache(2); 21 | Integer key = Integer.valueOf(1); 22 | Integer value = new Integer(3); 23 | cache.put(key, value); 24 | for (int i = 0; i < 3; ++i) { 25 | cache.put(i + 10, i * i); 26 | } 27 | System.gc(); 28 | assertEquals(value, cache.get(key)); 29 | } 30 | 31 | @SmallTest 32 | public void testLruAlgorithm() { 33 | LruCache cache = new LruCache(2); 34 | cache.put(0, new Integer(0)); 35 | for (int i = 0; i < 3; ++i) { 36 | cache.put(i + 1, i * i); 37 | cache.get(0); 38 | } 39 | System.gc(); 40 | assertEquals(Integer.valueOf(0), cache.get(0)); 41 | } 42 | 43 | private static final int TEST_COUNT = 10000; 44 | 45 | static class Accessor extends Thread { 46 | private final LruCache mMap; 47 | 48 | public Accessor(LruCache map) { 49 | mMap = map; 50 | } 51 | 52 | @Override 53 | public void run() { 54 | Log.v("TAG", "start get " + this); 55 | for (int i = 0; i < TEST_COUNT; ++i) { 56 | mMap.get(i % 2); 57 | } 58 | Log.v("TAG", "finish get " + this); 59 | } 60 | } 61 | 62 | @SuppressWarnings("unchecked") 63 | public void testConcurrentAccess() throws Exception { 64 | LruCache cache = new LruCache(4); 65 | cache.put(0, 0); 66 | cache.put(1, 1); 67 | Accessor accessor[] = new Accessor[4]; 68 | for (int i = 0; i < accessor.length; ++i) { 69 | accessor[i] = new Accessor(cache); 70 | } 71 | for (int i = 0; i < accessor.length; ++i) { 72 | accessor[i].start(); 73 | } 74 | for (int i = 0; i < accessor.length; ++i) { 75 | accessor[i].join(); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/gallery/MockImage.java: -------------------------------------------------------------------------------- 1 | package com.android.camera.gallery; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.net.Uri; 6 | 7 | import java.io.InputStream; 8 | 9 | public class MockImage implements IImage { 10 | private final long mId; 11 | private final long mTakenDate; 12 | private IImageList mContainer; 13 | 14 | public MockImage(long id, long takenDate) { 15 | mId = id; 16 | mTakenDate = takenDate; 17 | } 18 | 19 | public int getDegreesRotated() { 20 | return 0; 21 | } 22 | 23 | protected void setContainer(IImageList container) { 24 | this.mContainer = container; 25 | } 26 | 27 | public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels) { 28 | return null; 29 | } 30 | 31 | public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels, 32 | boolean rotateAsNeeded) { 33 | return null; 34 | } 35 | 36 | public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels, 37 | boolean rotateAsNeeded, boolean useNative) { 38 | return null; 39 | } 40 | 41 | public InputStream fullSizeImageData() { 42 | return null; 43 | } 44 | 45 | public long fullSizeImageId() { 46 | return mId; 47 | } 48 | 49 | public Uri fullSizeImageUri() { 50 | return null; 51 | } 52 | 53 | public IImageList getContainer() { 54 | return mContainer; 55 | } 56 | 57 | public String getDataPath() { 58 | return null; 59 | } 60 | 61 | public long getDateTaken() { 62 | return mTakenDate; 63 | } 64 | 65 | public String getDisplayName() { 66 | return null; 67 | } 68 | 69 | public int getHeight() { 70 | return 0; 71 | } 72 | 73 | public String getMimeType() { 74 | return null; 75 | } 76 | 77 | public String getTitle() { 78 | return null; 79 | } 80 | 81 | public int getWidth() { 82 | return 0; 83 | } 84 | 85 | public boolean isDrm() { 86 | return false; 87 | } 88 | 89 | public boolean isReadonly() { 90 | return false; 91 | } 92 | 93 | public Bitmap miniThumbBitmap() { 94 | return null; 95 | } 96 | 97 | public boolean rotateImageBy(int degrees) { 98 | return false; 99 | } 100 | 101 | public void setTitle(String name) { 102 | } 103 | 104 | public Bitmap thumbBitmap(boolean rotateAsNeeded) { 105 | return null; 106 | } 107 | 108 | public Uri thumbUri() { 109 | return null; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/com/android/camera/PreferenceGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import java.util.ArrayList; 20 | 21 | import android.content.Context; 22 | import android.util.AttributeSet; 23 | 24 | /** 25 | * A collection of CameraPreferences. It may contain other 26 | * PreferenceGroup and form a tree structure. 27 | */ 28 | public class PreferenceGroup extends CameraPreference { 29 | private ArrayList list = 30 | new ArrayList(); 31 | 32 | public PreferenceGroup(Context context, AttributeSet attrs) { 33 | super(context, attrs); 34 | } 35 | 36 | public void addChild(CameraPreference child) { 37 | list.add(child); 38 | } 39 | 40 | public void removePreference(int index) { 41 | list.remove(index); 42 | } 43 | 44 | public CameraPreference get(int index) { 45 | return list.get(index); 46 | } 47 | 48 | public int size() { 49 | return list.size(); 50 | } 51 | 52 | @Override 53 | public void reloadValue() { 54 | for (CameraPreference pref : list) { 55 | pref.reloadValue(); 56 | } 57 | } 58 | 59 | /** 60 | * Finds the preference with the given key recursively. Returns 61 | * null if cannot find. 62 | */ 63 | public ListPreference findPreference(String key) { 64 | // Find a leaf preference with the given key. Currently, the base 65 | // type of all "leaf" preference is "ListPreference". If we add some 66 | // other types later, we need to change the code. 67 | for (CameraPreference pref : list) { 68 | if (pref instanceof ListPreference) { 69 | ListPreference listPref = (ListPreference) pref; 70 | if(listPref.getKey().equals(key)) return listPref; 71 | } else if(pref instanceof PreferenceGroup) { 72 | ListPreference listPref = 73 | ((PreferenceGroup) pref).findPreference(key); 74 | if (listPref != null) return listPref; 75 | } 76 | } 77 | return null; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/com/android/camera/gallery/VideoList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.gallery; 18 | 19 | import android.content.ContentResolver; 20 | import android.database.Cursor; 21 | import android.net.Uri; 22 | import android.provider.MediaStore.Images; 23 | import android.provider.MediaStore.Video.Media; 24 | 25 | /** 26 | * A collection of all the VideoObject in gallery. 27 | */ 28 | public class VideoList extends BaseImageList { 29 | 30 | @SuppressWarnings("unused") 31 | private static final String TAG = "BaseImageList"; 32 | 33 | private static final String[] VIDEO_PROJECTION = new String[] { 34 | Media._ID, 35 | Media.DATE_TAKEN, 36 | Media.MINI_THUMB_MAGIC, 37 | Media.DATE_MODIFIED}; 38 | 39 | private static final int INDEX_ID = 0; 40 | private static final int INDEX_DATE_TAKEN = 1; 41 | private static final int INDEX_MIMI_THUMB_MAGIC = 2; 42 | private static final int INDEX_DATE_MODIFIED = 3; 43 | 44 | @Override 45 | protected BaseImage loadImageFromCursor(Cursor cursor) { 46 | long id = cursor.getLong(INDEX_ID); 47 | long dateTaken = cursor.getLong(INDEX_DATE_TAKEN); 48 | if (dateTaken == 0) { 49 | dateTaken = cursor.getLong(INDEX_DATE_MODIFIED) * 1000; 50 | } 51 | long miniThumbMagic = cursor.getLong(INDEX_MIMI_THUMB_MAGIC); 52 | return new VideoObject(mContentResolver, 53 | id, contentUri(id), 54 | miniThumbMagic, dateTaken); 55 | } 56 | 57 | public VideoList(ContentResolver resolver, Uri uri, int sort, 58 | String bucketId) { 59 | super(resolver, uri, sort, bucketId); 60 | } 61 | 62 | protected String whereClause() { 63 | return mBucketId != null 64 | ? Images.Media.BUCKET_ID + " = '" + mBucketId + "'" 65 | : null; 66 | } 67 | 68 | protected String[] whereClauseArgs() { 69 | return null; 70 | } 71 | 72 | @Override 73 | protected Cursor createCursor() { 74 | Cursor c = Images.Media.query( 75 | mContentResolver, mBaseUri, VIDEO_PROJECTION, 76 | whereClause(), whereClauseArgs(), sortOrder()); 77 | return c; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 29 | 34 | 38 | 46 | 54 | 60 | 61 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/GLOptionHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import static com.android.camera.ui.GLRootView.dpToPixel; 20 | import android.content.Context; 21 | import android.graphics.Rect; 22 | 23 | import javax.microedition.khronos.opengles.GL11; 24 | 25 | class GLOptionHeader extends GLView { 26 | private static final int FONT_COLOR = 0xFF979797; 27 | private static final float FONT_SIZE = 12; 28 | private static final int HORIZONTAL_PADDINGS = 4; 29 | private static final int VERTICAL_PADDINGS = 2; 30 | private static final int COLOR_OPTION_HEADER = 0xFF2B2B2B; 31 | 32 | private static int sHorizontalPaddings = -1; 33 | private static int sVerticalPaddings; 34 | 35 | private final StringTexture mTitle; 36 | private Texture mBackground; 37 | 38 | private static void initializeStaticVariables(Context context) { 39 | if (sHorizontalPaddings >= 0) return; 40 | sHorizontalPaddings = dpToPixel(context, HORIZONTAL_PADDINGS); 41 | sVerticalPaddings = dpToPixel(context, VERTICAL_PADDINGS); 42 | } 43 | 44 | public GLOptionHeader(Context context, String title) { 45 | initializeStaticVariables(context); 46 | 47 | float fontSize = GLRootView.dpToPixel(context, FONT_SIZE); 48 | mTitle = StringTexture.newInstance(title, fontSize, FONT_COLOR); 49 | setBackground(new ColorTexture(COLOR_OPTION_HEADER)); 50 | setPaddings(sHorizontalPaddings, 51 | sVerticalPaddings, sHorizontalPaddings, sVerticalPaddings); 52 | } 53 | 54 | public void setBackground(Texture background) { 55 | if (mBackground == background) return; 56 | mBackground = background; 57 | invalidate(); 58 | } 59 | 60 | @Override 61 | protected void onMeasure(int widthSpec, int heightSpec) { 62 | new MeasureHelper(this) 63 | .setPreferredContentSize(mTitle.getWidth(), mTitle.getHeight()) 64 | .measure(widthSpec, heightSpec); 65 | } 66 | 67 | @Override 68 | protected void render(GLRootView root, GL11 gl) { 69 | if (mBackground != null) { 70 | mBackground.draw(root, 0, 0, getWidth(), getHeight()); 71 | } 72 | Rect p = mPaddings; 73 | mTitle.draw(root, p.left, p.top); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/RestoreSettingsItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import static com.android.camera.ui.GLRootView.dpToPixel; 20 | import android.content.Context; 21 | import android.graphics.Color; 22 | import android.graphics.Rect; 23 | 24 | import javax.microedition.khronos.opengles.GL11; 25 | 26 | class RestoreSettingsItem extends GLView { 27 | private static final int FONT_COLOR = Color.WHITE; 28 | private static final float FONT_SIZE = 18; 29 | 30 | private static final int LEFT_PADDING = 20; 31 | private static final int RIGHT_PADDING = 4; 32 | private static final int TOP_PADDING = 2; 33 | private static final int BOTTOM_PADDING = 2; 34 | 35 | private static int sLeftPadding = -1; 36 | private static int sRightPadding; 37 | private static int sTopPadding; 38 | private static int sBottomPadding; 39 | private static float sFontSize; 40 | 41 | private final StringTexture mText; 42 | 43 | private static void initializeStaticVariables(Context context) { 44 | if (sLeftPadding >= 0) return; 45 | 46 | sLeftPadding = dpToPixel(context, LEFT_PADDING); 47 | sRightPadding = dpToPixel(context, RIGHT_PADDING); 48 | sTopPadding = dpToPixel(context, TOP_PADDING); 49 | sBottomPadding = dpToPixel(context, BOTTOM_PADDING); 50 | sFontSize = dpToPixel(context, FONT_SIZE); 51 | } 52 | 53 | public RestoreSettingsItem(Context context, String title) { 54 | initializeStaticVariables(context); 55 | mText = StringTexture.newInstance(title, sFontSize, FONT_COLOR); 56 | setPaddings(sLeftPadding, sTopPadding, sRightPadding, sBottomPadding); 57 | } 58 | 59 | @Override 60 | protected void onMeasure(int widthSpec, int heightSpec) { 61 | new MeasureHelper(this) 62 | .setPreferredContentSize(mText.getWidth(), mText.getHeight()) 63 | .measure(widthSpec, heightSpec); 64 | } 65 | 66 | @Override 67 | protected void render(GLRootView root, GL11 gl) { 68 | Rect p = mPaddings; 69 | int height = getHeight() - p.top - p.bottom; 70 | 71 | StringTexture title = mText; 72 | //TODO: cut the text if it is too long 73 | title.draw(root, p.left, p.top + (height - title.getHeight()) / 2); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/com/android/camera/gallery/LruCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.gallery; 18 | 19 | import java.lang.ref.ReferenceQueue; 20 | import java.lang.ref.WeakReference; 21 | import java.util.HashMap; 22 | import java.util.LinkedHashMap; 23 | import java.util.Map; 24 | 25 | /** 26 | * An LRU cache which stores recently inserted entries and all entries ever 27 | * inserted which still has a strong reference elsewhere. 28 | */ 29 | public class LruCache { 30 | 31 | private final HashMap mLruMap; 32 | private final HashMap> mWeakMap = 33 | new HashMap>(); 34 | private ReferenceQueue mQueue = new ReferenceQueue(); 35 | 36 | @SuppressWarnings("serial") 37 | public LruCache(final int capacity) { 38 | mLruMap = new LinkedHashMap(16, 0.75f, true) { 39 | @Override 40 | protected boolean removeEldestEntry(Map.Entry eldest) { 41 | return size() > capacity; 42 | } 43 | }; 44 | } 45 | 46 | private static class Entry extends WeakReference { 47 | K mKey; 48 | 49 | public Entry(K key, V value, ReferenceQueue queue) { 50 | super(value, queue); 51 | mKey = key; 52 | } 53 | } 54 | 55 | @SuppressWarnings("unchecked") 56 | private void cleanUpWeakMap() { 57 | Entry entry = (Entry) mQueue.poll(); 58 | while (entry != null) { 59 | mWeakMap.remove(entry.mKey); 60 | entry = (Entry) mQueue.poll(); 61 | } 62 | } 63 | 64 | public synchronized V put(K key, V value) { 65 | cleanUpWeakMap(); 66 | mLruMap.put(key, value); 67 | Entry entry = mWeakMap.put( 68 | key, new Entry(key, value, mQueue)); 69 | return entry == null ? null : entry.get(); 70 | } 71 | 72 | public synchronized V get(K key) { 73 | cleanUpWeakMap(); 74 | V value = mLruMap.get(key); 75 | if (value != null) return value; 76 | Entry entry = mWeakMap.get(key); 77 | return entry == null ? null : entry.get(); 78 | } 79 | 80 | public synchronized void clear() { 81 | mLruMap.clear(); 82 | mWeakMap.clear(); 83 | mQueue = new ReferenceQueue(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/com/android/camera/gallery/BaseImage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.gallery; 18 | 19 | import com.android.camera.BitmapManager; 20 | import com.android.camera.Util; 21 | 22 | import android.content.ContentResolver; 23 | import android.graphics.Bitmap; 24 | import android.net.Uri; 25 | import android.provider.MediaStore.Images; 26 | import android.util.Log; 27 | 28 | /** 29 | * Represents a particular image and provides access to the underlying bitmap 30 | * and two thumbnail bitmaps as well as other information such as the id, and 31 | * the path to the actual image data. 32 | */ 33 | public abstract class BaseImage implements IImage { 34 | private static final String TAG = "BaseImage"; 35 | protected ContentResolver mContentResolver; 36 | 37 | // Database field 38 | protected Uri mUri; 39 | protected long mId; 40 | private final long mDateTaken; 41 | 42 | protected BaseImage(ContentResolver cr, 43 | long id, Uri uri, long miniThumbMagic, 44 | long dateTaken) { 45 | mContentResolver = cr; 46 | mId = id; 47 | mUri = uri; 48 | mDateTaken = dateTaken; 49 | } 50 | 51 | @Override 52 | public boolean equals(Object other) { 53 | if (other == null || !(other instanceof Image)) return false; 54 | return mUri.equals(((Image) other).mUri); 55 | } 56 | 57 | @Override 58 | public int hashCode() { 59 | return mUri.hashCode(); 60 | } 61 | 62 | public Uri fullSizeImageUri() { 63 | return mUri; 64 | } 65 | 66 | public long getDateTaken() { 67 | return mDateTaken; 68 | } 69 | 70 | public int getDegreesRotated() { 71 | return 0; 72 | } 73 | 74 | public Bitmap miniThumbBitmap() { 75 | Bitmap b = null; 76 | try { 77 | long id = mId; 78 | b = BitmapManager.instance().getThumbnail(mContentResolver, id, 79 | Images.Thumbnails.MICRO_KIND, null, false); 80 | } catch (Throwable ex) { 81 | Log.e(TAG, "miniThumbBitmap got exception", ex); 82 | return null; 83 | } 84 | if (b != null) { 85 | b = Util.rotate(b, getDegreesRotated()); 86 | } 87 | return b; 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | return mUri.toString(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/functional/CameraTest.java: -------------------------------------------------------------------------------- 1 | package com.android.camera.functional; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Environment; 7 | import android.os.Process; 8 | import android.provider.MediaStore; 9 | import android.test.InstrumentationTestCase; 10 | import android.test.suitebuilder.annotation.LargeTest; 11 | import android.util.Log; 12 | 13 | import java.io.File; 14 | import java.lang.ref.WeakReference; 15 | import java.util.ArrayList; 16 | 17 | public class CameraTest extends InstrumentationTestCase { 18 | private static final String TAG = "CameraTest"; 19 | private static final String CAMERA_PACKAGE = "com.google.android.camera"; 20 | private static final String CAMERA_ACTIVITY = "com.android.camera.Camera"; 21 | private static final String CAMCORDER_ACTIVITY = "com.android.camera.VideoCamera"; 22 | 23 | @LargeTest 24 | public void testVideoCaptureIntentFdLeak() throws Exception { 25 | Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); 26 | intent.setClassName(CAMERA_PACKAGE, CAMCORDER_ACTIVITY); 27 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 28 | intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.parse("file://" 29 | + Environment.getExternalStorageDirectory().toString() 30 | + "test_fd_leak.3gp")); 31 | getInstrumentation().startActivitySync(intent).finish(); 32 | // Test if the fd is closed. 33 | for (File f: new File("/proc/" + Process.myPid() + "/fd").listFiles()) { 34 | assertEquals(-1, f.getCanonicalPath().indexOf("test_fd_leak.3gp")); 35 | } 36 | } 37 | 38 | @LargeTest 39 | public void testActivityLeak() throws Exception { 40 | checkActivityLeak(CAMERA_ACTIVITY); 41 | checkActivityLeak(CAMCORDER_ACTIVITY); 42 | } 43 | 44 | private void checkActivityLeak(String activityName) throws Exception { 45 | final int TEST_COUNT = 5; 46 | Intent intent = new Intent(); 47 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 48 | intent.setClassName(CAMERA_PACKAGE, activityName); 49 | ArrayList> refs = 50 | new ArrayList>(); 51 | for (int i = 0; i < TEST_COUNT; i++) { 52 | Activity activity = getInstrumentation().startActivitySync(intent); 53 | refs.add(new WeakReference(activity)); 54 | activity.finish(); 55 | getInstrumentation().waitForIdleSync(); 56 | activity = null; 57 | } 58 | Runtime.getRuntime().gc(); 59 | Runtime.getRuntime().runFinalization(); 60 | Runtime.getRuntime().gc(); 61 | int refCount = 0; 62 | for (WeakReference c: refs) { 63 | if (c.get() != null) refCount++; 64 | } 65 | // If applications are leaking activity, every reference is reachable. 66 | assertTrue(refCount != TEST_COUNT); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /res/xml/video_preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 19 | 21 | 28 | 36 | 44 | 50 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/com/android/camera/IconIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.content.Context; 20 | import android.content.res.Resources; 21 | import android.content.res.TypedArray; 22 | import android.graphics.drawable.Drawable; 23 | import android.util.AttributeSet; 24 | import android.widget.ImageView; 25 | 26 | import com.android.camera.R; 27 | 28 | /** 29 | * This class draws an icon which changes according to the mode. For example, 30 | * The flash icon can have on, off, and auto modes. The user can use 31 | * {@link #setMode(String)} to change the mode (and the icon). 32 | */ 33 | public class IconIndicator extends ImageView { 34 | 35 | private Drawable[] mIcons; 36 | private CharSequence[] mModes; 37 | 38 | public IconIndicator(Context context, AttributeSet attrs, int defStyle) { 39 | super(context, attrs, defStyle); 40 | TypedArray a = context.obtainStyledAttributes( 41 | attrs, R.styleable.IconIndicator, defStyle, 0); 42 | Drawable icons[] = loadIcons(context.getResources(), 43 | a.getResourceId(R.styleable.IconIndicator_icons, 0)); 44 | CharSequence modes[] = 45 | a.getTextArray(R.styleable.IconIndicator_modes); 46 | a.recycle(); 47 | 48 | setModesAndIcons(modes, icons); 49 | setImageDrawable(mIcons.length > 0 ? mIcons[0] : null); 50 | } 51 | 52 | public IconIndicator(Context context, AttributeSet attrs) { 53 | this(context, attrs, 0); 54 | } 55 | 56 | private Drawable[] loadIcons(Resources resources, int iconsId) { 57 | TypedArray array = resources.obtainTypedArray(iconsId); 58 | int n = array.length(); 59 | Drawable drawable[] = new Drawable[n]; 60 | for (int i = 0; i < n; ++i) { 61 | int id = array.getResourceId(i, 0); 62 | drawable[i] = id == 0 ? null : resources.getDrawable(id); 63 | } 64 | array.recycle(); 65 | return drawable; 66 | } 67 | 68 | private void setModesAndIcons(CharSequence[] modes, Drawable icons[]) { 69 | if (modes.length != icons.length || icons.length == 0) { 70 | throw new IllegalArgumentException(); 71 | } 72 | mIcons = icons; 73 | mModes = modes; 74 | } 75 | 76 | public void setMode(String mode) { 77 | for (int i = 0, n = mModes.length; i < n; ++i) { 78 | if (mModes[i].equals(mode)) { 79 | setImageDrawable(mIcons[i]); 80 | return; 81 | } 82 | } 83 | throw new IllegalArgumentException("unknown mode: " + mode); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /res/layout/camera_control.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 25 | 26 | 35 | 36 | 42 | 46 | 51 | 57 | 58 | 59 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/AbstractIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.content.Context; 20 | import android.graphics.Matrix; 21 | import android.graphics.Rect; 22 | import android.view.animation.AlphaAnimation; 23 | import android.view.animation.Transformation; 24 | 25 | import javax.microedition.khronos.opengles.GL11; 26 | 27 | abstract class AbstractIndicator extends GLView { 28 | private static final int DEFAULT_PADDING = 3; 29 | private int mOrientation = 0; 30 | 31 | abstract protected BitmapTexture getIcon(); 32 | 33 | public AbstractIndicator(Context context) { 34 | int padding = GLRootView.dpToPixel(context, DEFAULT_PADDING); 35 | setPaddings(padding, 0, padding, 0); 36 | } 37 | 38 | @Override 39 | protected void onMeasure(int widthSpec, int heightSpec) { 40 | BitmapTexture icon = getIcon(); 41 | new MeasureHelper(this) 42 | .setPreferredContentSize(icon.getWidth(), icon.getHeight()) 43 | .measure(widthSpec, heightSpec); 44 | } 45 | 46 | @Override 47 | protected void render(GLRootView root, GL11 gl) { 48 | BitmapTexture icon = getIcon(); 49 | if (icon != null) { 50 | Rect p = mPaddings; 51 | int width = getWidth() - p.left - p.right; 52 | int height = getHeight() - p.top - p.bottom; 53 | if (mOrientation != 0) { 54 | Transformation trans = root.pushTransform(); 55 | Matrix matrix = trans.getMatrix(); 56 | matrix.preTranslate(p.left + width / 2, p.top + height / 2); 57 | matrix.preRotate(-mOrientation); 58 | icon.draw(root, -icon.getWidth() / 2, -icon.getHeight() / 2); 59 | root.popTransform(); 60 | } else { 61 | icon.draw(root, 62 | p.left + (width - icon.getWidth()) / 2, 63 | p.top + (height - icon.getHeight()) / 2); 64 | } 65 | } 66 | } 67 | 68 | public void setOrientation(int orientation) { 69 | if (orientation % 90 != 0) throw new IllegalArgumentException(); 70 | orientation = orientation % 360; 71 | if (orientation < 0) orientation += 360; 72 | 73 | if (mOrientation == orientation) return; 74 | mOrientation = orientation; 75 | 76 | if (getGLRootView() != null) { 77 | AlphaAnimation anim = new AlphaAnimation(0.2f, 1); 78 | anim.setDuration(200); 79 | startAnimation(anim); 80 | } 81 | } 82 | 83 | abstract public GLView getPopupContent(); 84 | 85 | abstract public void overrideSettings(String key, String settings); 86 | 87 | abstract public void reloadPreferences(); 88 | } 89 | -------------------------------------------------------------------------------- /src/com/android/camera/IconListPreference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.content.Context; 20 | import android.content.res.Resources; 21 | import android.content.res.TypedArray; 22 | import android.util.AttributeSet; 23 | 24 | import com.android.camera.R; 25 | 26 | import java.util.List; 27 | 28 | /** A {@code ListPreference} where each entry has a corresponding icon. */ 29 | public class IconListPreference extends ListPreference { 30 | 31 | private int mIconIds[]; 32 | private int mLargeIconIds[]; 33 | 34 | public IconListPreference(Context context, AttributeSet attrs) { 35 | super(context, attrs); 36 | TypedArray a = context.obtainStyledAttributes( 37 | attrs, R.styleable.IconListPreference, 0, 0); 38 | Resources res = context.getResources(); 39 | mIconIds = getIconIds(res, a.getResourceId( 40 | R.styleable.IconListPreference_icons, 0)); 41 | mLargeIconIds = getIconIds(res, a.getResourceId( 42 | R.styleable.IconListPreference_largeIcons, 0)); 43 | a.recycle(); 44 | } 45 | 46 | public int[] getLargeIconIds() { 47 | return mLargeIconIds; 48 | } 49 | 50 | public int[] getIconIds() { 51 | return mIconIds; 52 | } 53 | 54 | public void setLargeIconIds(int[] largeIconIds) { 55 | mLargeIconIds = largeIconIds; 56 | } 57 | 58 | public void setIconIds(int[] iconIds) { 59 | mIconIds = iconIds; 60 | } 61 | 62 | private int[] getIconIds(Resources res, int iconsRes) { 63 | if (iconsRes == 0) return null; 64 | TypedArray array = res.obtainTypedArray(iconsRes); 65 | int n = array.length(); 66 | int ids[] = new int[n]; 67 | for (int i = 0; i < n; ++i) { 68 | ids[i] = array.getResourceId(i, 0); 69 | } 70 | array.recycle(); 71 | return ids; 72 | } 73 | 74 | @Override 75 | public void filterUnsupported(List supported) { 76 | CharSequence entryValues[] = getEntryValues(); 77 | IntArray iconIds = new IntArray(); 78 | IntArray largeIconIds = new IntArray(); 79 | 80 | for (int i = 0, len = entryValues.length; i < len; i++) { 81 | if (supported.indexOf(entryValues[i].toString()) >= 0) { 82 | if (mIconIds != null && mIconIds.length > i) { 83 | iconIds.add(mIconIds[i]); 84 | } 85 | if (mLargeIconIds != null && mLargeIconIds.length > i) { 86 | largeIconIds.add(mLargeIconIds[i]); 87 | } 88 | } 89 | } 90 | mIconIds = iconIds.toArray(new int[iconIds.size()]); 91 | mLargeIconIds = largeIconIds.toArray(new int[largeIconIds.size()]); 92 | super.filterUnsupported(supported); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /res/layout/video_camera.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 24 | 29 | 33 | 36 | 40 | 46 | 49 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/CameraEGLConfigChooser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.android.camera.ui; 17 | 18 | import android.opengl.GLSurfaceView.EGLConfigChooser; 19 | import javax.microedition.khronos.egl.EGL10; 20 | import javax.microedition.khronos.egl.EGLConfig; 21 | import javax.microedition.khronos.egl.EGLDisplay; 22 | 23 | /* 24 | * The code is copied/adapted from 25 | * android.opengl.GLSurfaceView.BaseConfigChooser. Here we try to 26 | * choose a configuration that support RGBA_8888 format and if possible, 27 | * with stencil buffer, but is not required. 28 | */ 29 | class CameraEGLConfigChooser implements EGLConfigChooser { 30 | 31 | private static final int COLOR_BITS = 8; 32 | 33 | private int mStencilBits; 34 | 35 | private final int mConfigSpec[] = new int[] { 36 | EGL10.EGL_RED_SIZE, COLOR_BITS, 37 | EGL10.EGL_GREEN_SIZE, COLOR_BITS, 38 | EGL10.EGL_BLUE_SIZE, COLOR_BITS, 39 | EGL10.EGL_ALPHA_SIZE, COLOR_BITS, 40 | EGL10.EGL_NONE 41 | }; 42 | 43 | public int getStencilBits() { 44 | return mStencilBits; 45 | } 46 | 47 | public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { 48 | int[] numConfig = new int[1]; 49 | if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, numConfig)) { 50 | throw new RuntimeException("eglChooseConfig failed"); 51 | } 52 | 53 | if (numConfig[0] <= 0) { 54 | throw new RuntimeException("No configs match configSpec"); 55 | } 56 | 57 | EGLConfig[] configs = new EGLConfig[numConfig[0]]; 58 | if (!egl.eglChooseConfig(display, 59 | mConfigSpec, configs, configs.length, numConfig)) { 60 | throw new RuntimeException(); 61 | } 62 | 63 | return chooseConfig(egl, display, configs); 64 | } 65 | 66 | private EGLConfig chooseConfig( 67 | EGL10 egl, EGLDisplay display, EGLConfig configs[]) { 68 | 69 | EGLConfig result = null; 70 | int minStencil = Integer.MAX_VALUE; 71 | int value[] = new int[1]; 72 | 73 | // Because we need only one bit of stencil, try to choose a config that 74 | // has stencil support but with smallest number of stencil bits. If 75 | // none is found, choose any one. 76 | for (int i = 0, n = configs.length; i < n; ++i) { 77 | if (egl.eglGetConfigAttrib( 78 | display, configs[i], EGL10.EGL_STENCIL_SIZE, value)) { 79 | if (value[0] == 0) continue; 80 | if (value[0] < minStencil) { 81 | minStencil = value[0]; 82 | result = configs[i]; 83 | } 84 | } else { 85 | throw new RuntimeException( 86 | "eglGetConfigAttrib error: " + egl.eglGetError()); 87 | } 88 | } 89 | if (result == null) result = configs[0]; 90 | egl.eglGetConfigAttrib( 91 | display, result, EGL10.EGL_STENCIL_SIZE, value); 92 | mStencilBits = value[0]; 93 | return result; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/com/android/camera/gallery/ImageList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.gallery; 18 | 19 | import android.content.ContentResolver; 20 | import android.database.Cursor; 21 | import android.net.Uri; 22 | import android.provider.MediaStore.Images.Media; 23 | 24 | /** 25 | * Represents an ordered collection of Image objects. Provides an API to add 26 | * and remove an image. 27 | */ 28 | public class ImageList extends BaseImageList implements IImageList { 29 | 30 | @SuppressWarnings("unused") 31 | private static final String TAG = "ImageList"; 32 | 33 | private static final String[] ACCEPTABLE_IMAGE_TYPES = 34 | new String[] { "image/jpeg", "image/png", "image/gif" }; 35 | 36 | /** 37 | * ImageList constructor. 38 | */ 39 | public ImageList(ContentResolver resolver, Uri imageUri, 40 | int sort, String bucketId) { 41 | super(resolver, imageUri, sort, bucketId); 42 | } 43 | 44 | private static final String WHERE_CLAUSE = 45 | "(" + Media.MIME_TYPE + " in (?, ?, ?))"; 46 | private static final String WHERE_CLAUSE_WITH_BUCKET_ID = 47 | WHERE_CLAUSE + " AND " + Media.BUCKET_ID + " = ?"; 48 | 49 | protected String whereClause() { 50 | return mBucketId == null ? WHERE_CLAUSE : WHERE_CLAUSE_WITH_BUCKET_ID; 51 | } 52 | 53 | protected String[] whereClauseArgs() { 54 | // TODO: Since mBucketId won't change, we should keep the array. 55 | if (mBucketId != null) { 56 | int count = ACCEPTABLE_IMAGE_TYPES.length; 57 | String[] result = new String[count + 1]; 58 | System.arraycopy(ACCEPTABLE_IMAGE_TYPES, 0, result, 0, count); 59 | result[count] = mBucketId; 60 | return result; 61 | } 62 | return ACCEPTABLE_IMAGE_TYPES; 63 | } 64 | 65 | @Override 66 | protected Cursor createCursor() { 67 | Cursor c = Media.query( 68 | mContentResolver, mBaseUri, IMAGE_PROJECTION, 69 | whereClause(), whereClauseArgs(), sortOrder()); 70 | return c; 71 | } 72 | 73 | static final String[] IMAGE_PROJECTION = new String[] { 74 | Media._ID, 75 | Media.DATE_TAKEN, 76 | Media.MINI_THUMB_MAGIC, 77 | Media.ORIENTATION, 78 | Media.DATE_MODIFIED}; 79 | 80 | private static final int INDEX_ID = 0; 81 | private static final int INDEX_DATE_TAKEN = 1; 82 | private static final int INDEX_MINI_THUMB_MAGIC = 2; 83 | private static final int INDEX_ORIENTATION = 3; 84 | private static final int INDEX_DATE_MODIFIED = 4; 85 | 86 | @Override 87 | protected BaseImage loadImageFromCursor(Cursor cursor) { 88 | long id = cursor.getLong(INDEX_ID); 89 | long dateTaken = cursor.getLong(INDEX_DATE_TAKEN); 90 | if (dateTaken == 0) { 91 | dateTaken = cursor.getLong(INDEX_DATE_MODIFIED) * 1000; 92 | } 93 | long miniThumbMagic = cursor.getLong(INDEX_MINI_THUMB_MAGIC); 94 | int orientation = cursor.getInt(INDEX_ORIENTATION); 95 | return new Image(mContentResolver, id, 96 | contentUri(id), miniThumbMagic, dateTaken, 97 | orientation); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /res/layout/attach_camera_control.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 25 | 31 | 33 | 36 | 38 | 39 | 42 | 45 | 47 | 48 | 51 | 54 | 56 | 57 | 58 | 68 | 72 | 75 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /src/com/android/camera/PreviewFrameLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.app.Activity; 20 | import android.content.Context; 21 | import android.util.AttributeSet; 22 | import android.util.DisplayMetrics; 23 | import android.view.ViewGroup; 24 | import android.widget.FrameLayout; 25 | 26 | /** 27 | * A layout which handles the preview aspect ratio and the position of 28 | * the gripper. 29 | */ 30 | public class PreviewFrameLayout extends ViewGroup { 31 | private static final int MIN_HORIZONTAL_MARGIN = 10; // 10dp 32 | 33 | /** A callback to be invoked when the preview frame's size changes. */ 34 | public interface OnSizeChangedListener { 35 | public void onSizeChanged(); 36 | } 37 | 38 | private double mAspectRatio = 4.0 / 3.0; 39 | private FrameLayout mFrame; 40 | private OnSizeChangedListener mSizeListener; 41 | private final DisplayMetrics mMetrics = new DisplayMetrics(); 42 | 43 | public PreviewFrameLayout(Context context, AttributeSet attrs) { 44 | super(context, attrs); 45 | ((Activity) context).getWindowManager() 46 | .getDefaultDisplay().getMetrics(mMetrics); 47 | } 48 | 49 | public void setOnSizeChangedListener(OnSizeChangedListener listener) { 50 | mSizeListener = listener; 51 | } 52 | 53 | @Override 54 | protected void onFinishInflate() { 55 | mFrame = (FrameLayout) findViewById(R.id.frame); 56 | if (mFrame == null) { 57 | throw new IllegalStateException( 58 | "must provide child with id as \"frame\""); 59 | } 60 | } 61 | 62 | public void setAspectRatio(double ratio) { 63 | if (ratio <= 0.0) throw new IllegalArgumentException(); 64 | 65 | if (mAspectRatio != ratio) { 66 | mAspectRatio = ratio; 67 | requestLayout(); 68 | } 69 | } 70 | 71 | @Override 72 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 73 | int frameWidth = getWidth(); 74 | int frameHeight = getHeight(); 75 | 76 | FrameLayout f = mFrame; 77 | int horizontalPadding = f.getPaddingLeft() + f.getPaddingRight(); 78 | int verticalPadding = f.getPaddingBottom() + f.getPaddingTop(); 79 | int previewHeight = frameHeight - verticalPadding; 80 | int previewWidth = frameWidth - horizontalPadding; 81 | 82 | // resize frame and preview for aspect ratio 83 | if (previewWidth > previewHeight * mAspectRatio) { 84 | previewWidth = (int) (previewHeight * mAspectRatio + .5); 85 | } else { 86 | previewHeight = (int) (previewWidth / mAspectRatio + .5); 87 | } 88 | 89 | frameWidth = previewWidth + horizontalPadding; 90 | frameHeight = previewHeight + verticalPadding; 91 | 92 | int hSpace = ((r - l) - frameWidth) / 2; 93 | int vSpace = ((b - t) - frameHeight) / 2; 94 | mFrame.measure( 95 | MeasureSpec.makeMeasureSpec(frameWidth, MeasureSpec.EXACTLY), 96 | MeasureSpec.makeMeasureSpec(frameHeight, MeasureSpec.EXACTLY)); 97 | mFrame.layout(l + hSpace, t + vSpace, r - hSpace, b - vSpace); 98 | if (mSizeListener != null) { 99 | mSizeListener.onSizeChanged(); 100 | } 101 | } 102 | } 103 | 104 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/stress/SwitchPreview.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.stress; 18 | 19 | import com.android.camera.VideoCamera; 20 | 21 | import android.app.Instrumentation; 22 | import android.content.Intent; 23 | import android.test.ActivityInstrumentationTestCase2; 24 | import android.test.suitebuilder.annotation.LargeTest; 25 | import android.os.Environment; 26 | import android.util.Log; 27 | 28 | import java.io.BufferedWriter; 29 | import java.io.FileWriter; 30 | 31 | /** 32 | * Junit / Instrumentation test case for camera test 33 | * 34 | * Running the test suite: 35 | * 36 | * adb shell am instrument \ 37 | * -e class com.android.camera.stress.SwitchPreview \ 38 | * -w com.android.camera.tests/com.android.camera.CameraStressTestRunner 39 | * 40 | */ 41 | public class SwitchPreview extends ActivityInstrumentationTestCase2 { 42 | private String TAG = "SwitchPreview"; 43 | private static final int TOTAL_NUMBER_OF_SWITCHING = 200; 44 | private static final long WAIT_FOR_PREVIEW = 4000; 45 | 46 | private static final String CAMERA_TEST_OUTPUT_FILE = 47 | Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; 48 | private BufferedWriter mOut; 49 | private FileWriter mfstream; 50 | 51 | public SwitchPreview() { 52 | super("com.google.android.camera", VideoCamera.class); 53 | } 54 | 55 | @Override 56 | protected void setUp() throws Exception { 57 | getActivity(); 58 | prepareOutputFile(); 59 | super.setUp(); 60 | } 61 | 62 | @Override 63 | protected void tearDown() throws Exception { 64 | getActivity().finish(); 65 | closeOutputFile(); 66 | super.tearDown(); 67 | } 68 | 69 | private void prepareOutputFile(){ 70 | try{ 71 | mfstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); 72 | mOut = new BufferedWriter(mfstream); 73 | } catch (Exception e){ 74 | assertTrue("Camera Switch Mode",false); 75 | } 76 | } 77 | 78 | private void closeOutputFile() { 79 | try { 80 | mOut.write("\n"); 81 | mOut.close(); 82 | mfstream.close(); 83 | } catch (Exception e) { 84 | assertTrue("CameraSwitchMode close output", false); 85 | } 86 | } 87 | 88 | @LargeTest 89 | public void testSwitchMode() { 90 | //Switching the video and the video recorder mode 91 | Instrumentation inst = getInstrumentation(); 92 | try{ 93 | mOut.write("Camera Switch Mode:\n"); 94 | mOut.write("No of loops :" + TOTAL_NUMBER_OF_SWITCHING + "\n"); 95 | mOut.write("loop: "); 96 | for (int i=0; i< TOTAL_NUMBER_OF_SWITCHING; i++) { 97 | Thread.sleep(WAIT_FOR_PREVIEW); 98 | Intent intent = new Intent(); 99 | intent.setClassName("com.google.android.camera", 100 | "com.android.camera.VideoCamera"); 101 | getActivity().startActivity(intent); 102 | Thread.sleep(WAIT_FOR_PREVIEW); 103 | intent.setClassName("com.google.android.camera", 104 | "com.android.camera.Camera"); 105 | getActivity().startActivity(intent); 106 | mOut.write(" ," + i); 107 | mOut.flush(); 108 | } 109 | } catch (Exception e){ 110 | Log.v(TAG, e.toString()); 111 | } 112 | assertTrue("testSwitchMode",true); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/com/android/camera/RotateImageView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.content.Context; 20 | import android.graphics.Canvas; 21 | import android.graphics.Rect; 22 | import android.graphics.drawable.Drawable; 23 | import android.util.AttributeSet; 24 | import android.view.animation.AnimationUtils; 25 | import android.widget.ImageView; 26 | 27 | /** 28 | * A @{code ImageView} which can rotate it's content. 29 | */ 30 | public class RotateImageView extends ImageView { 31 | 32 | @SuppressWarnings("unused") 33 | private static final String TAG = "RotateImageView"; 34 | 35 | private static final int ANIMATION_SPEED = 180; // 180 deg/sec 36 | 37 | private int mCurrentDegree = 0; // [0, 359] 38 | private int mStartDegree = 0; 39 | private int mTargetDegree = 0; 40 | 41 | private boolean mClockwise = false; 42 | 43 | private long mAnimationStartTime = 0; 44 | private long mAnimationEndTime = 0; 45 | 46 | public RotateImageView(Context context, AttributeSet attrs) { 47 | super(context, attrs); 48 | } 49 | 50 | public void setDegree(int degree) { 51 | // make sure in the range of [0, 359] 52 | degree = degree >= 0 ? degree % 360 : degree % 360 + 360; 53 | if (degree == mTargetDegree) return; 54 | 55 | mTargetDegree = degree; 56 | mStartDegree = mCurrentDegree; 57 | mAnimationStartTime = AnimationUtils.currentAnimationTimeMillis(); 58 | 59 | int diff = mTargetDegree - mCurrentDegree; 60 | diff = diff >= 0 ? diff : 360 + diff; // make it in range [0, 359] 61 | 62 | // Make it in range [-179, 180]. That's the shorted distance between the 63 | // two angles 64 | diff = diff > 180 ? diff - 360 : diff; 65 | 66 | mClockwise = diff >= 0; 67 | mAnimationEndTime = mAnimationStartTime 68 | + Math.abs(diff) * 1000 / ANIMATION_SPEED; 69 | 70 | invalidate(); 71 | } 72 | 73 | @Override 74 | protected void onDraw(Canvas canvas) { 75 | 76 | Drawable drawable = getDrawable(); 77 | if (drawable == null) return; 78 | 79 | Rect bounds = drawable.getBounds(); 80 | int w = bounds.right - bounds.left; 81 | int h = bounds.bottom - bounds.top; 82 | 83 | if (w == 0 || h == 0) return; // nothing to draw 84 | 85 | if (mCurrentDegree != mTargetDegree) { 86 | long time = AnimationUtils.currentAnimationTimeMillis(); 87 | if (time < mAnimationEndTime) { 88 | int deltaTime = (int)(time - mAnimationStartTime); 89 | int degree = mStartDegree + ANIMATION_SPEED 90 | * (mClockwise ? deltaTime : -deltaTime) / 1000; 91 | degree = degree >= 0 ? degree % 360 : degree % 360 + 360; 92 | mCurrentDegree = degree; 93 | invalidate(); 94 | } else { 95 | mCurrentDegree = mTargetDegree; 96 | } 97 | } 98 | 99 | int left = getPaddingLeft(); 100 | int top = getPaddingTop(); 101 | int right = getPaddingRight(); 102 | int bottom = getPaddingBottom(); 103 | int width = getWidth() - left - right; 104 | int height = getHeight() - top - bottom; 105 | 106 | int saveCount = canvas.getSaveCount(); 107 | canvas.translate(left + width / 2, top + height / 2); 108 | canvas.rotate(-mCurrentDegree); 109 | canvas.translate(-w / 2, -h / 2); 110 | drawable.draw(canvas); 111 | canvas.restoreToCount(saveCount); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/BitmapTexture.java: -------------------------------------------------------------------------------- 1 | package com.android.camera.ui; 2 | 3 | import com.android.camera.Util; 4 | 5 | import android.graphics.Bitmap; 6 | import android.opengl.GLUtils; 7 | 8 | import javax.microedition.khronos.opengles.GL11; 9 | import javax.microedition.khronos.opengles.GL11Ext; 10 | 11 | abstract class BitmapTexture extends BasicTexture { 12 | 13 | @SuppressWarnings("unused") 14 | private static final String TAG = "Texture"; 15 | 16 | protected BitmapTexture() { 17 | super(null, 0, STATE_UNLOADED); 18 | } 19 | 20 | @Override 21 | public int getWidth() { 22 | if (mWidth == UNSPECIFIED) getBitmap(); 23 | return mWidth; 24 | } 25 | 26 | @Override 27 | public int getHeight() { 28 | if (mWidth == UNSPECIFIED) getBitmap(); 29 | return mHeight; 30 | } 31 | 32 | protected abstract Bitmap getBitmap(); 33 | 34 | protected abstract void freeBitmap(Bitmap bitmap); 35 | 36 | private void uploadToGL(GL11 gl) throws GLOutOfMemoryException { 37 | Bitmap bitmap = getBitmap(); 38 | int glError = GL11.GL_NO_ERROR; 39 | if (bitmap != null) { 40 | int[] textureId = new int[1]; 41 | try { 42 | // Define a vertically flipped crop rectangle for 43 | // OES_draw_texture. 44 | int width = bitmap.getWidth(); 45 | int height = bitmap.getHeight(); 46 | int[] cropRect = {0, height, width, -height}; 47 | 48 | // Upload the bitmap to a new texture. 49 | gl.glGenTextures(1, textureId, 0); 50 | gl.glBindTexture(GL11.GL_TEXTURE_2D, textureId[0]); 51 | gl.glTexParameteriv(GL11.GL_TEXTURE_2D, 52 | GL11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect, 0); 53 | gl.glTexParameteri(GL11.GL_TEXTURE_2D, 54 | GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); 55 | gl.glTexParameteri(GL11.GL_TEXTURE_2D, 56 | GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); 57 | gl.glTexParameterf(GL11.GL_TEXTURE_2D, 58 | GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); 59 | gl.glTexParameterf(GL11.GL_TEXTURE_2D, 60 | GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); 61 | 62 | int widthExt = Util.nextPowerOf2(width); 63 | int heightExt = Util.nextPowerOf2(height); 64 | int format = GLUtils.getInternalFormat(bitmap); 65 | int type = GLUtils.getType(bitmap); 66 | 67 | mTextureWidth = widthExt; 68 | mTextureHeight = heightExt; 69 | gl.glTexImage2D(GL11.GL_TEXTURE_2D, 0, format, 70 | widthExt, heightExt, 0, format, type, null); 71 | GLUtils.texSubImage2D( 72 | GL11.GL_TEXTURE_2D, 0, 0, 0, bitmap, format, type); 73 | } finally { 74 | freeBitmap(bitmap); 75 | } 76 | if (glError == GL11.GL_OUT_OF_MEMORY) { 77 | throw new GLOutOfMemoryException(); 78 | } 79 | if (glError != GL11.GL_NO_ERROR) { 80 | mId = 0; 81 | mState = STATE_UNLOADED; 82 | throw new RuntimeException( 83 | "Texture upload fail, glError " + glError); 84 | } else { 85 | // Update texture state. 86 | mGL = gl; 87 | mId = textureId[0]; 88 | mState = BitmapTexture.STATE_LOADED; 89 | } 90 | } else { 91 | mState = STATE_ERROR; 92 | throw new RuntimeException("Texture load fail, no bitmap"); 93 | } 94 | } 95 | 96 | @Override 97 | protected boolean bind(GLRootView root, GL11 gl) { 98 | if (mState == BitmapTexture.STATE_UNLOADED || mGL != gl) { 99 | mState = BitmapTexture.STATE_UNLOADED; 100 | try { 101 | uploadToGL(gl); 102 | } catch (GLOutOfMemoryException e) { 103 | root.handleLowMemory(); 104 | return false; 105 | } 106 | } else { 107 | gl.glBindTexture(GL11.GL_TEXTURE_2D, getId()); 108 | } 109 | return true; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/com/android/camera/PreferenceInflater.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import org.xmlpull.v1.XmlPullParser; 20 | import org.xmlpull.v1.XmlPullParserException; 21 | 22 | import java.io.IOException; 23 | import java.lang.reflect.Constructor; 24 | import java.util.ArrayList; 25 | import java.util.HashMap; 26 | 27 | import android.content.Context; 28 | import android.util.AttributeSet; 29 | import android.util.Xml; 30 | import android.view.InflateException; 31 | 32 | /** 33 | * Inflate CameraPreference from XML resource. 34 | */ 35 | public class PreferenceInflater { 36 | private static final String PACKAGE_NAME = 37 | PreferenceInflater.class.getPackage().getName(); 38 | 39 | private static final Class[] CTOR_SIGNATURE = 40 | new Class[] {Context.class, AttributeSet.class}; 41 | private static final HashMap> sConstructorMap = 42 | new HashMap>(); 43 | 44 | private Context mContext; 45 | 46 | public PreferenceInflater(Context context) { 47 | mContext = context; 48 | } 49 | 50 | public CameraPreference inflate(int resId) { 51 | return inflate(mContext.getResources().getXml(resId)); 52 | } 53 | 54 | private CameraPreference newPreference(String tagName, Object[] args) { 55 | String name = PACKAGE_NAME + "." + tagName; 56 | Constructor constructor = sConstructorMap.get(name); 57 | try { 58 | if (constructor == null) { 59 | // Class not found in the cache, see if it's real, and try to 60 | // add it 61 | Class clazz = mContext.getClassLoader().loadClass(name); 62 | constructor = clazz.getConstructor(CTOR_SIGNATURE); 63 | sConstructorMap.put(name, constructor); 64 | } 65 | return (CameraPreference) constructor.newInstance(args); 66 | } catch (NoSuchMethodException e) { 67 | throw new InflateException("Error inflating class " + name, e); 68 | } catch (ClassNotFoundException e) { 69 | throw new InflateException("No such class: " + name, e); 70 | } catch (Exception e) { 71 | throw new InflateException("While create instance of" + name, e); 72 | } 73 | } 74 | 75 | private CameraPreference inflate(XmlPullParser parser) { 76 | 77 | AttributeSet attrs = Xml.asAttributeSet(parser); 78 | ArrayList list = new ArrayList(); 79 | Object args[] = new Object[]{mContext, attrs}; 80 | 81 | try { 82 | for (int type = parser.next(); 83 | type != XmlPullParser.END_DOCUMENT; type = parser.next()) { 84 | if (type != XmlPullParser.START_TAG) continue; 85 | CameraPreference pref = newPreference(parser.getName(), args); 86 | 87 | int depth = parser.getDepth(); 88 | if (depth > list.size()) { 89 | list.add(pref); 90 | } else { 91 | list.set(depth - 1, pref); 92 | } 93 | if (depth > 1) { 94 | ((PreferenceGroup) list.get(depth - 2)).addChild(pref); 95 | } 96 | } 97 | 98 | if (list.size() == 0) { 99 | throw new InflateException("No root element found"); 100 | } 101 | return list.get(0); 102 | } catch (XmlPullParserException e) { 103 | throw new InflateException(e); 104 | } catch (IOException e) { 105 | throw new InflateException(parser.getPositionDescription(), e); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/BasicIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.content.Context; 20 | 21 | import com.android.camera.IconListPreference; 22 | import com.android.camera.R; 23 | import com.android.camera.Util; 24 | import com.android.camera.ui.GLListView.OnItemSelectedListener; 25 | 26 | class BasicIndicator extends AbstractIndicator { 27 | private static final int COLOR_OPTION_ITEM_HIGHLIGHT = 0xFF181818; 28 | 29 | private final ResourceTexture mIcon[]; 30 | private final IconListPreference mPreference; 31 | protected int mIndex; 32 | private GLListView mPopupContent; 33 | private PreferenceAdapter mModel; 34 | private String mOverride; 35 | 36 | public BasicIndicator(Context context, IconListPreference preference) { 37 | super(context); 38 | mPreference = preference; 39 | mIcon = new ResourceTexture[preference.getLargeIconIds().length]; 40 | mIndex = preference.findIndexOfValue(preference.getValue()); 41 | } 42 | 43 | // Set the override and/or reload the value from preferences. 44 | private void updateContent(String override, boolean reloadValue) { 45 | if (!reloadValue && Util.equals(mOverride, override)) return; 46 | IconListPreference pref = mPreference; 47 | mOverride = override; 48 | int index = pref.findIndexOfValue( 49 | override == null ? pref.getValue() : override); 50 | if (mIndex != index) { 51 | mIndex = index; 52 | invalidate(); 53 | } 54 | } 55 | 56 | @Override 57 | public void overrideSettings(String key, String settings) { 58 | IconListPreference pref = mPreference; 59 | if (!pref.getKey().equals(key)) return; 60 | updateContent(settings, false); 61 | } 62 | 63 | @Override 64 | public void reloadPreferences() { 65 | if (mModel != null) mModel.reload(); 66 | updateContent(null, true); 67 | } 68 | 69 | @Override 70 | public GLView getPopupContent() { 71 | if (mPopupContent == null) { 72 | Context context = getGLRootView().getContext(); 73 | mPopupContent = new GLListView(context); 74 | mPopupContent.setHighLight( 75 | new ColorTexture(COLOR_OPTION_ITEM_HIGHLIGHT)); 76 | mPopupContent.setScroller(new NinePatchTexture( 77 | context, R.drawable.scrollbar_handle_vertical)); 78 | mModel = new PreferenceAdapter(context, mPreference); 79 | mPopupContent.setOnItemSelectedListener(new MyListener(mModel)); 80 | mPopupContent.setDataModel(mModel); 81 | } 82 | mModel.overrideSettings(mOverride); 83 | return mPopupContent; 84 | } 85 | 86 | protected void onPreferenceChanged(int newIndex) { 87 | if (newIndex == mIndex) return; 88 | mIndex = newIndex; 89 | invalidate(); 90 | } 91 | 92 | private class MyListener implements OnItemSelectedListener { 93 | 94 | private final PreferenceAdapter mAdapter; 95 | 96 | public MyListener(PreferenceAdapter adapter) { 97 | mAdapter = adapter; 98 | } 99 | 100 | public void onItemSelected(GLView view, int position) { 101 | mAdapter.onItemSelected(view, position); 102 | onPreferenceChanged(position - 1); 103 | } 104 | } 105 | 106 | @Override 107 | protected ResourceTexture getIcon() { 108 | int index = mIndex; 109 | if (mIcon[index] == null) { 110 | Context context = getGLRootView().getContext(); 111 | mIcon[index] = new ResourceTexture( 112 | context, mPreference.getLargeIconIds()[index]); 113 | } 114 | return mIcon[index]; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/com/android/camera/ListPreference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.content.Context; 20 | import android.content.SharedPreferences; 21 | import android.content.res.TypedArray; 22 | import android.util.AttributeSet; 23 | 24 | import com.android.camera.R; 25 | 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | /** 30 | * A type of CameraPreference whose number of possible values 31 | * is limited. 32 | */ 33 | public class ListPreference extends CameraPreference { 34 | 35 | private final String mKey; 36 | private String mValue; 37 | private final String mDefaultValue; 38 | 39 | private CharSequence[] mEntries; 40 | private CharSequence[] mEntryValues; 41 | private boolean mLoaded = false; 42 | 43 | public ListPreference(Context context, AttributeSet attrs) { 44 | super(context, attrs); 45 | 46 | TypedArray a = context.obtainStyledAttributes( 47 | attrs, R.styleable.ListPreference, 0, 0); 48 | 49 | mKey = Util.checkNotNull( 50 | a.getString(R.styleable.ListPreference_key)); 51 | mDefaultValue = a.getString(R.styleable.ListPreference_defaultValue); 52 | 53 | setEntries(a.getTextArray(R.styleable.ListPreference_entries)); 54 | setEntryValues(a.getTextArray( 55 | R.styleable.ListPreference_entryValues)); 56 | a.recycle(); 57 | } 58 | 59 | public String getKey() { 60 | return mKey; 61 | } 62 | 63 | public CharSequence[] getEntries() { 64 | return mEntries; 65 | } 66 | 67 | public CharSequence[] getEntryValues() { 68 | return mEntryValues; 69 | } 70 | 71 | public void setEntries(CharSequence entries[]) { 72 | mEntries = entries == null ? new CharSequence[0] : entries; 73 | } 74 | 75 | public void setEntryValues(CharSequence values[]) { 76 | mEntryValues = values == null ? new CharSequence[0] : values; 77 | } 78 | 79 | public String getValue() { 80 | if (!mLoaded) { 81 | mValue = getSharedPreferences().getString(mKey, mDefaultValue); 82 | mLoaded = true; 83 | } 84 | return mValue; 85 | } 86 | 87 | public void setValue(String value) { 88 | if (findIndexOfValue(value) < 0) throw new IllegalArgumentException(); 89 | mValue = value; 90 | persistStringValue(value); 91 | } 92 | 93 | public void setValueIndex(int index) { 94 | setValue(mEntryValues[index].toString()); 95 | } 96 | 97 | public int findIndexOfValue(String value) { 98 | for (int i = 0, n = mEntryValues.length; i < n; ++i) { 99 | if (Util.equals(mEntryValues[i], value)) return i; 100 | } 101 | return -1; 102 | } 103 | 104 | public String getEntry() { 105 | return mEntries[findIndexOfValue(getValue())].toString(); 106 | } 107 | 108 | protected void persistStringValue(String value) { 109 | SharedPreferences.Editor editor = getSharedPreferences().edit(); 110 | editor.putString(mKey, value); 111 | editor.apply(); 112 | } 113 | 114 | @Override 115 | public void reloadValue() { 116 | this.mLoaded = false; 117 | } 118 | 119 | public void filterUnsupported(List supported) { 120 | ArrayList entries = new ArrayList(); 121 | ArrayList entryValues = new ArrayList(); 122 | for (int i = 0, len = mEntryValues.length; i < len; i++) { 123 | if (supported.indexOf(mEntryValues[i].toString()) >= 0) { 124 | entries.add(mEntries[i]); 125 | entryValues.add(mEntryValues[i]); 126 | } 127 | } 128 | int size = entries.size(); 129 | mEntries = entries.toArray(new CharSequence[size]); 130 | mEntryValues = entryValues.toArray(new CharSequence[size]); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/RotatePane.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.graphics.Matrix; 20 | import android.view.MotionEvent; 21 | 22 | import javax.microedition.khronos.opengles.GL11; 23 | 24 | 25 | class RotatePane extends GLView { 26 | 27 | public static final int UP = 0; 28 | public static final int RIGHT = 1; 29 | public static final int DOWN = 2; 30 | public static final int LEFT = 3; 31 | 32 | private int mOrientation = 0; 33 | 34 | private GLView mChild; 35 | 36 | @Override 37 | protected void onLayout( 38 | boolean change, int left, int top, int right, int bottom) { 39 | int width = right - left; 40 | int height = bottom - top; 41 | switch (mOrientation) { 42 | case UP: 43 | case DOWN: 44 | mChild.layout(0, 0, width, height); 45 | break; 46 | case LEFT: 47 | case RIGHT: 48 | mChild.layout(0, 0, height, width); 49 | break; 50 | } 51 | } 52 | 53 | @Override 54 | protected void onMeasure(int widthSpec, int heightSpec) { 55 | GLView c = mChild; 56 | switch(mOrientation) { 57 | case UP: 58 | case DOWN: 59 | c.measure(widthSpec, heightSpec); 60 | setMeasuredSize(c.getMeasuredWidth(), c.getMeasuredHeight()); 61 | break; 62 | case LEFT: 63 | case RIGHT: 64 | mChild.measure(heightSpec, widthSpec); 65 | setMeasuredSize(c.getMeasuredHeight(), c.getMeasuredWidth()); 66 | } 67 | } 68 | 69 | @Override 70 | protected void render(GLRootView view, GL11 gl) { 71 | 72 | if (mOrientation == UP) { 73 | mChild.render(view, gl); 74 | return; 75 | } 76 | 77 | view.pushTransform(); 78 | Matrix matrix = view.getTransformation().getMatrix(); 79 | float width = getWidth(); 80 | float height = getHeight(); 81 | switch (mOrientation) { 82 | case DOWN: 83 | matrix.preRotate(180, width / 2, height / 2); 84 | break; 85 | case LEFT: 86 | matrix.preRotate(270, height / 2, height / 2); 87 | break; 88 | case RIGHT: 89 | matrix.preRotate(90, width / 2, width / 2); 90 | break; 91 | } 92 | mChild.render(view, gl); 93 | view.popTransform(); 94 | } 95 | 96 | @Override 97 | protected boolean dispatchTouchEvent(MotionEvent event) { 98 | float x = event.getX(); 99 | float y = event.getY(); 100 | float width = getWidth(); 101 | float height = getHeight(); 102 | switch (mOrientation) { 103 | case DOWN: event.setLocation(width - x, height - y); break; 104 | case LEFT: event.setLocation(height - y, x); break; 105 | case RIGHT: event.setLocation(y, width - x); break; 106 | } 107 | boolean result = mChild.dispatchTouchEvent(event); 108 | event.setLocation(x, y); 109 | return result; 110 | } 111 | 112 | public void setOrientation(int orientation) { 113 | if (mOrientation == orientation) return; 114 | mOrientation = orientation; 115 | requestLayout(); 116 | } 117 | 118 | public void setContent(GLView view) { 119 | if (mChild == view) return; 120 | 121 | if (mChild != null) super.clearComponents(); 122 | mChild = view; 123 | if (view != null) super.addComponent(view); 124 | requestLayout(); 125 | } 126 | 127 | @Override 128 | public void addComponent(GLView view) { 129 | throw new UnsupportedOperationException("use setContent(GLView)"); 130 | } 131 | 132 | @Override 133 | public void clearComponents() { 134 | throw new UnsupportedOperationException("use setContent(null)"); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/PreferenceAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import android.content.Context; 20 | 21 | import com.android.camera.IconListPreference; 22 | import com.android.camera.ListPreference; 23 | import com.android.camera.Util; 24 | 25 | import java.util.ArrayList; 26 | 27 | class PreferenceAdapter 28 | implements GLListView.Model, GLListView.OnItemSelectedListener { 29 | 30 | private static final int ICON_NONE = 0; 31 | 32 | private final ArrayList mContent = new ArrayList(); 33 | private final ListPreference mPreference; 34 | private String mOverride; 35 | 36 | public PreferenceAdapter(Context context, ListPreference preference) { 37 | mPreference = preference; 38 | generateContent(context, preference); 39 | } 40 | 41 | public void reload() { 42 | updateContent(null, true); 43 | } 44 | 45 | public void overrideSettings(String settings) { 46 | updateContent(settings, false); 47 | } 48 | 49 | private void updateContent(String settings, boolean reloadValues) { 50 | if (!reloadValues && Util.equals(settings, mOverride)) return; 51 | mOverride = settings; 52 | 53 | CharSequence[] values = mPreference.getEntryValues(); 54 | String value = mPreference.getValue(); 55 | if (settings == null) { 56 | for (int i = 1, n = mContent.size(); i < n; ++i) { 57 | GLOptionItem item = (GLOptionItem) mContent.get(i); 58 | item.setChecked(values[i - 1].equals(value)); 59 | item.setEnabled(true); 60 | } 61 | } else { 62 | for (int i = 1, n = mContent.size(); i < n; ++i) { 63 | GLOptionItem item = (GLOptionItem) mContent.get(i); 64 | boolean checked = values[i - 1].equals(settings); 65 | item.setChecked(checked); 66 | item.setEnabled(checked); 67 | } 68 | } 69 | } 70 | 71 | private void generateContent(Context context, ListPreference preference) { 72 | GLOptionHeader header = 73 | new GLOptionHeader(context, preference.getTitle()); 74 | mContent.add(header); 75 | CharSequence[] entries = preference.getEntries(); 76 | CharSequence[] values = preference.getEntryValues(); 77 | String value = preference.getValue(); 78 | int [] icons = null; 79 | if (preference instanceof IconListPreference) { 80 | IconListPreference iPref = (IconListPreference) preference; 81 | icons = iPref.getIconIds(); 82 | } 83 | for (int i = 0, n = entries.length; i < n; ++i) { 84 | GLOptionItem item = new GLOptionItem( 85 | context, icons == null || icons.length == 0 ? ICON_NONE : icons[i], 86 | entries[i].toString()); 87 | item.setChecked(values[i].equals(value)); 88 | mContent.add(item); 89 | } 90 | } 91 | 92 | public void onItemSelected(GLView view, int position) { 93 | if (mOverride != null) return; 94 | ListPreference pref = mPreference; 95 | CharSequence[] values = pref.getEntryValues(); 96 | if (position < values.length + 1) { 97 | int index = position - 1; 98 | int oldIndex = pref.findIndexOfValue(pref.getValue()); 99 | if (oldIndex != index) { 100 | synchronized (pref.getSharedPreferences()) { 101 | pref.setValueIndex(index); 102 | } 103 | ((GLOptionItem) mContent.get(1 + oldIndex)).setChecked(false); 104 | ((GLOptionItem) view).setChecked(true); 105 | } 106 | return; 107 | } 108 | } 109 | 110 | public GLView getView(int index) { 111 | return mContent.get(index); 112 | } 113 | 114 | public boolean isSelectable(int index) { 115 | return mContent.get(index) instanceof GLOptionItem; 116 | } 117 | 118 | public int size() { 119 | return mContent.size(); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/com/android/camera/BitmapManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.content.ContentResolver; 20 | import android.graphics.Bitmap; 21 | import android.graphics.BitmapFactory; 22 | import android.provider.MediaStore.Images; 23 | import android.provider.MediaStore.Video; 24 | import android.util.Log; 25 | 26 | import java.io.FileDescriptor; 27 | import java.util.WeakHashMap; 28 | 29 | /** 30 | * Provides utilities to decode bitmap, get thumbnail, and cancel the 31 | * operations. 32 | * 33 | *

The function {@link #decodeFileDescriptor(FileDescriptor, 34 | * BitmapFactory.Options)} is used to decode a bitmap. During decoding another 35 | * thread can cancel it using the function {@link #cancelThreadDecoding(Thread, 36 | * ContentResolver)} specifying the {@code Thread} which is in decoding. 37 | * 38 | *

{@code cancelThreadDecoding(Thread,ContentResolver)} is sticky until 39 | * {@code allowThreadDecoding(Thread) } is called. 40 | */ 41 | public class BitmapManager { 42 | private static final String TAG = "BitmapManager"; 43 | private static enum State {CANCEL, ALLOW} 44 | private static class ThreadStatus { 45 | public State mState = State.ALLOW; 46 | public BitmapFactory.Options mOptions; 47 | 48 | @Override 49 | public String toString() { 50 | String s; 51 | if (mState == State.CANCEL) { 52 | s = "Cancel"; 53 | } else if (mState == State.ALLOW) { 54 | s = "Allow"; 55 | } else { 56 | s = "?"; 57 | } 58 | s = "thread state = " + s + ", options = " + mOptions; 59 | return s; 60 | } 61 | } 62 | 63 | private final WeakHashMap mThreadStatus = 64 | new WeakHashMap(); 65 | 66 | private static BitmapManager sManager = null; 67 | 68 | private BitmapManager() { 69 | } 70 | 71 | /** 72 | * Get thread status and create one if specified. 73 | */ 74 | private synchronized ThreadStatus getOrCreateThreadStatus(Thread t) { 75 | ThreadStatus status = mThreadStatus.get(t); 76 | if (status == null) { 77 | status = new ThreadStatus(); 78 | mThreadStatus.put(t, status); 79 | } 80 | return status; 81 | } 82 | 83 | public synchronized boolean canThreadDecoding(Thread t) { 84 | ThreadStatus status = mThreadStatus.get(t); 85 | if (status == null) { 86 | // allow decoding by default 87 | return true; 88 | } 89 | 90 | boolean result = (status.mState != State.CANCEL); 91 | return result; 92 | } 93 | 94 | /** 95 | * Gets the thumbnail of the given ID of the original image. 96 | * 97 | *

This method wraps around @{code getThumbnail} in {@code 98 | * android.provider.MediaStore}. It provides the ability to cancel it. 99 | */ 100 | public Bitmap getThumbnail(ContentResolver cr, long origId, int kind, 101 | BitmapFactory.Options options, boolean isVideo) { 102 | Thread t = Thread.currentThread(); 103 | ThreadStatus status = getOrCreateThreadStatus(t); 104 | 105 | if (!canThreadDecoding(t)) { 106 | Log.d(TAG, "Thread " + t + " is not allowed to decode."); 107 | return null; 108 | } 109 | 110 | try { 111 | if (isVideo) { 112 | return Video.Thumbnails.getThumbnail(cr, origId, t.getId(), 113 | kind, null); 114 | } else { 115 | return Images.Thumbnails.getThumbnail(cr, origId, t.getId(), 116 | kind, null); 117 | } 118 | } finally { 119 | synchronized (status) { 120 | status.notifyAll(); 121 | } 122 | } 123 | } 124 | 125 | public static synchronized BitmapManager instance() { 126 | if (sManager == null) { 127 | sManager = new BitmapManager(); 128 | } 129 | return sManager; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /tests/src/com/android/camera/power/ImageAndVideoCapture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.power; 18 | 19 | import com.android.camera.Camera; 20 | 21 | import android.app.Instrumentation; 22 | import android.test.ActivityInstrumentationTestCase2; 23 | import android.test.suitebuilder.annotation.LargeTest; 24 | import android.util.Log; 25 | import android.view.KeyEvent; 26 | import android.content.Intent; 27 | /** 28 | * Junit / Instrumentation test case for camera power measurement 29 | * 30 | * Running the test suite: 31 | * 32 | * adb shell am instrument \ 33 | * -e com.android.camera.power.ImageAndVideoCapture \ 34 | * -w com.android.camera.tests/android.test.InstrumentationTestRunner 35 | * 36 | */ 37 | 38 | public class ImageAndVideoCapture extends ActivityInstrumentationTestCase2 { 39 | private String TAG = "ImageAndVideoCapture"; 40 | private static final int TOTAL_NUMBER_OF_IMAGECAPTURE = 5; 41 | private static final int TOTAL_NUMBER_OF_VIDEOCAPTURE = 5; 42 | private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 1500; //1.5 sedconds 43 | private static final long WAIT_FOR_VIDEO_CAPTURE_TO_BE_TAKEN = 10000; //10 seconds 44 | private static final long WAIT_FOR_PREVIEW = 1500; //1.5 seconds 45 | private static final long WAIT_FOR_STABLE_STATE = 2000; //2 seconds 46 | 47 | public ImageAndVideoCapture() { 48 | super("com.google.android.camera", Camera.class); 49 | } 50 | 51 | @Override 52 | protected void setUp() throws Exception { 53 | getActivity(); 54 | super.setUp(); 55 | } 56 | 57 | @Override 58 | protected void tearDown() throws Exception { 59 | super.tearDown(); 60 | } 61 | 62 | @LargeTest 63 | public void testLaunchCamera() { 64 | // This test case capture the baseline for the image preview. 65 | try { 66 | Thread.sleep(WAIT_FOR_STABLE_STATE); 67 | } catch (Exception e) { 68 | Log.v(TAG, e.toString()); 69 | assertTrue("testImageCaptureDoNothing", false); 70 | } 71 | assertTrue("testImageCaptureDoNothing", true); 72 | } 73 | 74 | @LargeTest 75 | public void testCapture5Image() { 76 | // This test case will use the default camera setting 77 | Instrumentation inst = getInstrumentation(); 78 | try { 79 | for (int i = 0; i < TOTAL_NUMBER_OF_IMAGECAPTURE; i++) { 80 | Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); 81 | inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP); 82 | inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); 83 | Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); 84 | } 85 | Thread.sleep(WAIT_FOR_STABLE_STATE); 86 | } catch (Exception e) { 87 | Log.v(TAG, e.toString()); 88 | assertTrue("testImageCapture", false); 89 | } 90 | assertTrue("testImageCapture", true); 91 | } 92 | 93 | @LargeTest 94 | public void testCapture5Videos() { 95 | // This test case will use the default camera setting 96 | Instrumentation inst = getInstrumentation(); 97 | try { 98 | // Switch to the video mode 99 | Intent intent = new Intent(); 100 | intent.setClassName("com.google.android.camera", 101 | "com.android.camera.VideoCamera"); 102 | getActivity().startActivity(intent); 103 | for (int i = 0; i < TOTAL_NUMBER_OF_VIDEOCAPTURE; i++) { 104 | Thread.sleep(WAIT_FOR_PREVIEW); 105 | // record a video 106 | inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); 107 | Thread.sleep(WAIT_FOR_VIDEO_CAPTURE_TO_BE_TAKEN); 108 | inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); 109 | Thread.sleep(WAIT_FOR_PREVIEW); 110 | } 111 | Thread.sleep(WAIT_FOR_STABLE_STATE); 112 | } catch (Exception e) { 113 | Log.v(TAG, e.toString()); 114 | assertTrue("testVideoCapture", false); 115 | } 116 | assertTrue("testVideoCapture", true); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/com/android/camera/ShutterButton.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.widget.ImageView; 22 | 23 | /** 24 | * A button designed to be used for the on-screen shutter button. 25 | * It's currently an {@code ImageView} that can call a delegate when the 26 | * pressed state changes. 27 | */ 28 | public class ShutterButton extends ImageView { 29 | /** 30 | * A callback to be invoked when a ShutterButton's pressed state changes. 31 | */ 32 | public interface OnShutterButtonListener { 33 | /** 34 | * Called when a ShutterButton has been pressed. 35 | * 36 | * @param b The ShutterButton that was pressed. 37 | */ 38 | void onShutterButtonFocus(ShutterButton b, boolean pressed); 39 | void onShutterButtonClick(ShutterButton b); 40 | } 41 | 42 | private OnShutterButtonListener mListener; 43 | private boolean mOldPressed; 44 | 45 | public ShutterButton(Context context) { 46 | super(context); 47 | } 48 | 49 | public ShutterButton(Context context, AttributeSet attrs) { 50 | super(context, attrs); 51 | } 52 | 53 | public ShutterButton(Context context, AttributeSet attrs, int defStyle) { 54 | super(context, attrs, defStyle); 55 | } 56 | 57 | public void setOnShutterButtonListener(OnShutterButtonListener listener) { 58 | mListener = listener; 59 | } 60 | 61 | /** 62 | * Hook into the drawable state changing to get changes to isPressed -- the 63 | * onPressed listener doesn't always get called when the pressed state 64 | * changes. 65 | */ 66 | @Override 67 | protected void drawableStateChanged() { 68 | super.drawableStateChanged(); 69 | final boolean pressed = isPressed(); 70 | if (pressed != mOldPressed) { 71 | if (!pressed) { 72 | // When pressing the physical camera button the sequence of 73 | // events is: 74 | // focus pressed, optional camera pressed, focus released. 75 | // We want to emulate this sequence of events with the shutter 76 | // button. When clicking using a trackball button, the view 77 | // system changes the the drawable state before posting click 78 | // notification, so the sequence of events is: 79 | // pressed(true), optional click, pressed(false) 80 | // When clicking using touch events, the view system changes the 81 | // drawable state after posting click notification, so the 82 | // sequence of events is: 83 | // pressed(true), pressed(false), optional click 84 | // Since we're emulating the physical camera button, we want to 85 | // have the same order of events. So we want the optional click 86 | // callback to be delivered before the pressed(false) callback. 87 | // 88 | // To do this, we delay the posting of the pressed(false) event 89 | // slightly by pushing it on the event queue. This moves it 90 | // after the optional click notification, so our client always 91 | // sees events in this sequence: 92 | // pressed(true), optional click, pressed(false) 93 | post(new Runnable() { 94 | public void run() { 95 | callShutterButtonFocus(pressed); 96 | } 97 | }); 98 | } else { 99 | callShutterButtonFocus(pressed); 100 | } 101 | mOldPressed = pressed; 102 | } 103 | } 104 | 105 | private void callShutterButtonFocus(boolean pressed) { 106 | if (mListener != null) { 107 | mListener.onShutterButtonFocus(this, pressed); 108 | } 109 | } 110 | 111 | @Override 112 | public boolean performClick() { 113 | boolean result = super.performClick(); 114 | if (mListener != null) { 115 | mListener.onShutterButtonClick(this); 116 | } 117 | return result; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/com/android/camera/ui/CamcorderHeadUpDisplay.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.android.camera.ui; 18 | 19 | import com.android.camera.CameraSettings; 20 | import com.android.camera.ListPreference; 21 | import com.android.camera.PreferenceGroup; 22 | 23 | import android.content.Context; 24 | import android.util.Log; 25 | 26 | public class CamcorderHeadUpDisplay extends HeadUpDisplay { 27 | 28 | private static final String TAG = "CamcorderHeadUpDisplay"; 29 | 30 | private OtherSettingsIndicator mOtherSettings; 31 | private int mInitialOrientation; 32 | private BasicIndicator mVideoQualitySettings; 33 | private float[] mInitialZoomRatios; 34 | private ZoomIndicator mZoomIndicator; 35 | private Context mContext; 36 | 37 | public CamcorderHeadUpDisplay(Context context) { 38 | super(context); 39 | mContext = context; 40 | } 41 | 42 | public void initialize(Context context, PreferenceGroup group, 43 | float[] initialZoomRatios, int initialOrientation) { 44 | mInitialOrientation = initialOrientation; 45 | mInitialZoomRatios = initialZoomRatios; 46 | super.initialize(context, group); 47 | } 48 | 49 | @Override 50 | protected void initializeIndicatorBar( 51 | Context context, PreferenceGroup group) { 52 | super.initializeIndicatorBar(context, group); 53 | 54 | ListPreference[] prefs = getListPreferences(group, 55 | CameraSettings.KEY_FOCUS_MODE, 56 | CameraSettings.KEY_EXPOSURE, 57 | CameraSettings.KEY_SCENE_MODE, 58 | CameraSettings.KEY_PICTURE_SIZE, 59 | CameraSettings.KEY_JPEG_QUALITY, 60 | CameraSettings.KEY_COLOR_EFFECT); 61 | 62 | mOtherSettings = new OtherSettingsIndicator(context, prefs); 63 | mOtherSettings.setOnRestorePreferencesClickedRunner(new Runnable() { 64 | public void run() { 65 | if (mListener != null) { 66 | mListener.onRestorePreferencesClicked(); 67 | } 68 | } 69 | }); 70 | mIndicatorBar.addComponent(mOtherSettings); 71 | 72 | addIndicator(context, group, CameraSettings.KEY_WHITE_BALANCE); 73 | addIndicator(context, group, CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE); 74 | 75 | mVideoQualitySettings = addIndicator(context, group, CameraSettings.KEY_VIDEO_QUALITY); 76 | 77 | if (mInitialZoomRatios != null) { 78 | mZoomIndicator = new ZoomIndicator(mContext); 79 | mZoomIndicator.setZoomRatios(mInitialZoomRatios); 80 | mIndicatorBar.addComponent(mZoomIndicator); 81 | } else { 82 | mZoomIndicator = null; 83 | } 84 | 85 | addIndicator(context, group, CameraSettings.KEY_CAMERA_ID); 86 | 87 | mIndicatorBar.setOrientation(mInitialOrientation); 88 | } 89 | 90 | public void setZoomListener(ZoomControllerListener listener) { 91 | // The rendering thread won't access listener variable, so we don't 92 | // need to do concurrency protection here 93 | if (mZoomIndicator != null) { 94 | mZoomIndicator.setZoomListener(listener); 95 | } 96 | } 97 | 98 | public void setZoomIndex(int index) { 99 | if (mZoomIndicator != null) { 100 | GLRootView root = getGLRootView(); 101 | if (root != null) { 102 | synchronized (root) { 103 | mZoomIndicator.setZoomIndex(index); 104 | } 105 | } else { 106 | mZoomIndicator.setZoomIndex(index); 107 | } 108 | } 109 | } 110 | 111 | /** 112 | * Sets the zoom rations the camera driver provides. This methods must be 113 | * called before setZoomListener() and 114 | * setZoomIndex() 115 | */ 116 | public void setZoomRatios(float[] zoomRatios) { 117 | GLRootView root = getGLRootView(); 118 | if (root != null) { 119 | synchronized(root) { 120 | setZoomRatiosLocked(zoomRatios); 121 | } 122 | } else { 123 | setZoomRatiosLocked(zoomRatios); 124 | } 125 | } 126 | 127 | private void setZoomRatiosLocked(float[] zoomRatios) { 128 | mZoomIndicator.setZoomRatios(zoomRatios); 129 | } 130 | 131 | public void setVideoQualityControlsEnabled(boolean enabled) { 132 | if (mVideoQualitySettings != null) { 133 | mVideoQualitySettings.setEnabled(enabled); 134 | } 135 | } 136 | } 137 | --------------------------------------------------------------------------------