├── MODULE_LICENSE_APACHE2
├── res
├── drawable-hdpi
│ ├── photo_inner.9.png
│ ├── appwidget_bg.9.png
│ ├── ic_menu_3d_globe.png
│ ├── camera_crop_height.png
│ ├── camera_crop_width.png
│ ├── ic_gallery_empty2.png
│ ├── ic_launcher_camera.png
│ ├── indicator_autocrop.png
│ ├── detail_photo_border.9.png
│ ├── ic_launcher_gallery.png
│ ├── ic_menu_view_details.png
│ ├── btn_check_buttonless_on.png
│ ├── btn_check_buttonless_off.png
│ ├── ic_error_mms_video_overlay.png
│ ├── ic_gallery_video_overlay.png
│ ├── ic_menu_camera_video_view.png
│ ├── ic_missing_thumbnail_video.png
│ ├── image_border_bg_normal.9.png
│ ├── btn_camera_arrow_left_press.png
│ ├── btn_camera_arrow_right_press.png
│ ├── frame_gallery_preview_album.png
│ ├── frame_overlay_gallery_camera.png
│ ├── frame_overlay_gallery_folder.png
│ ├── frame_overlay_gallery_video.png
│ ├── ic_menu_multiselect_gallery.png
│ ├── ic_missing_thumbnail_picture.png
│ ├── image_border_bg_focus_blue.9.png
│ ├── btn_camera_arrow_left_default.png
│ ├── btn_camera_arrow_left_selected.png
│ ├── btn_camera_arrow_right_default.png
│ ├── btn_camera_arrow_right_selected.png
│ ├── ic_btn_actionmenu_play_default.png
│ ├── ic_btn_actionmenu_play_pressed.png
│ ├── ic_btn_actionmenu_play_selected.png
│ ├── ic_btn_actionmenu_share_default.png
│ ├── ic_btn_actionmenu_share_pressed.png
│ ├── image_border_bg_pressed_blue.9.png
│ ├── frame_gallery_preview_album_mask.png
│ ├── ic_btn_actionmenu_attach_default.png
│ ├── ic_btn_actionmenu_attach_pressed.png
│ ├── ic_btn_actionmenu_attach_selected.png
│ ├── ic_btn_actionmenu_cancel_default.png
│ ├── ic_btn_actionmenu_cancel_pressed.png
│ ├── ic_btn_actionmenu_cancel_selected.png
│ ├── ic_btn_actionmenu_delete_default.png
│ ├── ic_btn_actionmenu_delete_pressed.png
│ ├── ic_btn_actionmenu_delete_selected.png
│ ├── ic_btn_actionmenu_set_as_default.png
│ ├── ic_btn_actionmenu_set_as_pressed.png
│ ├── ic_btn_actionmenu_set_as_selected.png
│ ├── ic_btn_actionmenu_share_selected.png
│ ├── frame_gallery_preview_album_pressed.png
│ └── frame_gallery_preview_album_selected.png
├── drawable-mdpi
│ ├── photo_inner.9.png
│ ├── appwidget_bg.9.png
│ ├── ic_menu_3d_globe.png
│ ├── camera_crop_height.png
│ ├── camera_crop_width.png
│ ├── ic_gallery_empty2.png
│ ├── ic_launcher_camera.png
│ ├── indicator_autocrop.png
│ ├── detail_photo_border.9.png
│ ├── ic_launcher_gallery.png
│ ├── ic_menu_view_details.png
│ ├── btn_check_buttonless_on.png
│ ├── btn_check_buttonless_off.png
│ ├── ic_error_mms_video_overlay.png
│ ├── ic_gallery_video_overlay.png
│ ├── ic_menu_camera_video_view.png
│ ├── ic_missing_thumbnail_video.png
│ ├── image_border_bg_normal.9.png
│ ├── btn_camera_arrow_left_press.png
│ ├── btn_camera_arrow_right_press.png
│ ├── frame_gallery_preview_album.png
│ ├── frame_overlay_gallery_camera.png
│ ├── frame_overlay_gallery_folder.png
│ ├── frame_overlay_gallery_video.png
│ ├── ic_menu_multiselect_gallery.png
│ ├── ic_missing_thumbnail_picture.png
│ ├── image_border_bg_focus_blue.9.png
│ ├── btn_camera_arrow_left_default.png
│ ├── btn_camera_arrow_left_selected.png
│ ├── btn_camera_arrow_right_default.png
│ ├── btn_camera_arrow_right_selected.png
│ ├── ic_btn_actionmenu_play_default.png
│ ├── ic_btn_actionmenu_play_pressed.png
│ ├── ic_btn_actionmenu_play_selected.png
│ ├── ic_btn_actionmenu_share_default.png
│ ├── ic_btn_actionmenu_share_pressed.png
│ ├── image_border_bg_pressed_blue.9.png
│ ├── frame_gallery_preview_album_mask.png
│ ├── ic_btn_actionmenu_attach_default.png
│ ├── ic_btn_actionmenu_attach_pressed.png
│ ├── ic_btn_actionmenu_attach_selected.png
│ ├── ic_btn_actionmenu_cancel_default.png
│ ├── ic_btn_actionmenu_cancel_pressed.png
│ ├── ic_btn_actionmenu_cancel_selected.png
│ ├── ic_btn_actionmenu_delete_default.png
│ ├── ic_btn_actionmenu_delete_pressed.png
│ ├── ic_btn_actionmenu_delete_selected.png
│ ├── ic_btn_actionmenu_set_as_default.png
│ ├── ic_btn_actionmenu_set_as_pressed.png
│ ├── ic_btn_actionmenu_set_as_selected.png
│ ├── ic_btn_actionmenu_share_selected.png
│ ├── frame_gallery_preview_album_pressed.png
│ └── frame_gallery_preview_album_selected.png
├── values-land
│ └── dimens.xml
├── values
│ ├── colors.xml
│ ├── attrs.xml
│ └── styles.xml
├── anim
│ ├── slide_in.xml
│ ├── slide_out.xml
│ ├── slide_in_vertical.xml
│ ├── slide_out_vertical.xml
│ ├── transition_in.xml
│ ├── footer_appear.xml
│ ├── footer_disappear.xml
│ └── transition_out.xml
├── xml
│ ├── appwidget_info.xml
│ └── gallery_preferences.xml
├── drawable
│ ├── ic_menu_attach.xml
│ ├── ic_menu_cancel.xml
│ ├── grid_background.xml
│ ├── ic_menu_share.xml
│ ├── ic_menu_camera_play.xml
│ ├── ic_menu_delete.xml
│ ├── ic_menu_set_as.xml
│ ├── btn_camera_arrow_left.xml
│ ├── btn_camera_arrow_right.xml
│ └── frame_gallery_preview.xml
├── layout
│ ├── delete_image.xml
│ ├── custom_gallery_title.xml
│ ├── gallerypicker.xml
│ ├── photo_frame.xml
│ ├── gallery_picker_item.xml
│ ├── gallerypicker_no_images.xml
│ ├── movie_view.xml
│ ├── cropimage.xml
│ ├── image_gallery.xml
│ └── viewimage.xml
└── values-nl
│ └── arrays.xml
├── Android.mk
├── tests
├── Android.mk
├── src
│ └── com
│ │ └── android
│ │ └── camera
│ │ ├── UnitTests.java
│ │ ├── CameraLaunchPerformance.java
│ │ ├── gallery
│ │ ├── MockImageList.java
│ │ ├── LruCacheUnitTests.java
│ │ ├── MockImage.java
│ │ └── ImageListUberUnitTests.java
│ │ └── BitmapManagerUnitTests.java
└── AndroidManifest.xml
├── src
└── com
│ └── android
│ └── camera
│ ├── PickWallpaper.java
│ ├── NoSearchActivity.java
│ ├── GallerySettings.java
│ ├── gallery
│ ├── SingleImageList.java
│ ├── IImageList.java
│ ├── LruCache.java
│ ├── IImage.java
│ ├── DrmImageList.java
│ ├── VideoObject.java
│ ├── VideoList.java
│ ├── ImageList.java
│ ├── Image.java
│ ├── UriImage.java
│ └── BaseImage.java
│ ├── ReverseGeocoderTask.java
│ ├── Wallpaper.java
│ ├── DeleteImage.java
│ ├── RotateBitmap.java
│ ├── MonitoredActivity.java
│ ├── PhotoAppWidgetBind.java
│ ├── ActionMenuButton.java
│ ├── MovieView.java
│ ├── GalleryPickerItem.java
│ ├── PhotoAppWidgetConfigure.java
│ ├── EvenlySpacedLayout.java
│ ├── ImageLoader.java
│ ├── BitmapManager.java
│ └── PhotoAppWidgetProvider.java
└── CleanSpec.mk
/MODULE_LICENSE_APACHE2:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/photo_inner.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/photo_inner.9.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/photo_inner.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/photo_inner.9.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/appwidget_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/appwidget_bg.9.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_menu_3d_globe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_menu_3d_globe.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/appwidget_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/appwidget_bg.9.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_menu_3d_globe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_menu_3d_globe.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/camera_crop_height.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/camera_crop_height.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/camera_crop_width.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/camera_crop_width.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_gallery_empty2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_gallery_empty2.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher_camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_launcher_camera.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/indicator_autocrop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/indicator_autocrop.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/camera_crop_height.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/camera_crop_height.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/camera_crop_width.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/camera_crop_width.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_gallery_empty2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_gallery_empty2.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher_camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_launcher_camera.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/indicator_autocrop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/indicator_autocrop.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/detail_photo_border.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/detail_photo_border.9.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher_gallery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_launcher_gallery.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_menu_view_details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_menu_view_details.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/detail_photo_border.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/detail_photo_border.9.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher_gallery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_launcher_gallery.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_menu_view_details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_menu_view_details.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_check_buttonless_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/btn_check_buttonless_on.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/btn_check_buttonless_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/btn_check_buttonless_on.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_check_buttonless_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/btn_check_buttonless_off.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_error_mms_video_overlay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_error_mms_video_overlay.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_gallery_video_overlay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_gallery_video_overlay.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_menu_camera_video_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_menu_camera_video_view.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_missing_thumbnail_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_missing_thumbnail_video.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/image_border_bg_normal.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/image_border_bg_normal.9.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/btn_check_buttonless_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/btn_check_buttonless_off.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_error_mms_video_overlay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_error_mms_video_overlay.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_gallery_video_overlay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_gallery_video_overlay.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_menu_camera_video_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_menu_camera_video_view.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_missing_thumbnail_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_missing_thumbnail_video.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/image_border_bg_normal.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/image_border_bg_normal.9.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_camera_arrow_left_press.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/btn_camera_arrow_left_press.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_camera_arrow_right_press.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/btn_camera_arrow_right_press.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/frame_gallery_preview_album.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/frame_gallery_preview_album.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/frame_overlay_gallery_camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/frame_overlay_gallery_camera.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/frame_overlay_gallery_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/frame_overlay_gallery_folder.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/frame_overlay_gallery_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/frame_overlay_gallery_video.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_menu_multiselect_gallery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_menu_multiselect_gallery.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_missing_thumbnail_picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_missing_thumbnail_picture.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/image_border_bg_focus_blue.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/image_border_bg_focus_blue.9.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/btn_camera_arrow_left_press.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/btn_camera_arrow_left_press.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/btn_camera_arrow_right_press.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/btn_camera_arrow_right_press.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/frame_gallery_preview_album.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/frame_gallery_preview_album.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/frame_overlay_gallery_camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/frame_overlay_gallery_camera.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/frame_overlay_gallery_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/frame_overlay_gallery_folder.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/frame_overlay_gallery_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/frame_overlay_gallery_video.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_menu_multiselect_gallery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_menu_multiselect_gallery.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_missing_thumbnail_picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_missing_thumbnail_picture.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/image_border_bg_focus_blue.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/image_border_bg_focus_blue.9.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_camera_arrow_left_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/btn_camera_arrow_left_default.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_camera_arrow_left_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/btn_camera_arrow_left_selected.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_camera_arrow_right_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/btn_camera_arrow_right_default.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_camera_arrow_right_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/btn_camera_arrow_right_selected.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_play_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_play_default.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_play_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_play_pressed.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_play_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_play_selected.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_share_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_share_default.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_share_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_share_pressed.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/image_border_bg_pressed_blue.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/image_border_bg_pressed_blue.9.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/btn_camera_arrow_left_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/btn_camera_arrow_left_default.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/btn_camera_arrow_left_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/btn_camera_arrow_left_selected.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/btn_camera_arrow_right_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/btn_camera_arrow_right_default.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/btn_camera_arrow_right_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/btn_camera_arrow_right_selected.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_play_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_play_default.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_play_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_play_pressed.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_play_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_play_selected.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_share_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_share_default.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_share_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_share_pressed.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/image_border_bg_pressed_blue.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/image_border_bg_pressed_blue.9.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/frame_gallery_preview_album_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/frame_gallery_preview_album_mask.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_attach_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_attach_default.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_attach_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_attach_pressed.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_attach_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_attach_selected.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_cancel_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_cancel_default.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_cancel_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_cancel_pressed.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_cancel_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_cancel_selected.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_delete_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_delete_default.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_delete_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_delete_pressed.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_delete_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_delete_selected.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_set_as_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_set_as_default.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_set_as_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_set_as_pressed.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_set_as_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_set_as_selected.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_btn_actionmenu_share_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/ic_btn_actionmenu_share_selected.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/frame_gallery_preview_album_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/frame_gallery_preview_album_mask.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_attach_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_attach_default.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_attach_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_attach_pressed.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_attach_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_attach_selected.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_cancel_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_cancel_default.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_cancel_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_cancel_pressed.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_cancel_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_cancel_selected.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_delete_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_delete_default.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_delete_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_delete_pressed.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_delete_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_delete_selected.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_set_as_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_set_as_default.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_set_as_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_set_as_pressed.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_set_as_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_set_as_selected.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_btn_actionmenu_share_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/ic_btn_actionmenu_share_selected.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/frame_gallery_preview_album_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/frame_gallery_preview_album_pressed.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/frame_gallery_preview_album_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-hdpi/frame_gallery_preview_album_selected.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/frame_gallery_preview_album_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/frame_gallery_preview_album_pressed.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/frame_gallery_preview_album_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyanogenMod/android_packages_apps_Gallery/HEAD/res/drawable-mdpi/frame_gallery_preview_album_selected.png
--------------------------------------------------------------------------------
/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 := Gallery
9 | LOCAL_CERTIFICATE := media
10 |
11 | include $(BUILD_PACKAGE)
12 |
13 | # Use the following include to make our test apk.
14 | include $(call all-makefiles-under,$(LOCAL_PATH))
15 |
--------------------------------------------------------------------------------
/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 | LOCAL_CERTIFICATE := media
7 |
8 | LOCAL_JAVA_LIBRARIES := android.test.runner
9 |
10 | # Include all test java files.
11 | LOCAL_SRC_FILES := $(call all-java-files-under, src)
12 |
13 | LOCAL_PACKAGE_NAME := GalleryTests
14 |
15 | LOCAL_INSTRUMENTATION_FOR := Gallery
16 |
17 | include $(BUILD_PACKAGE)
18 |
19 |
20 |
--------------------------------------------------------------------------------
/res/values-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 | #B2191919
22 |
23 |
--------------------------------------------------------------------------------
/res/anim/slide_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
22 |
--------------------------------------------------------------------------------
/res/anim/slide_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
22 |
--------------------------------------------------------------------------------
/src/com/android/camera/PickWallpaper.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 | /**
20 | * Wallpaper picker for the camera application.
21 | * This just redirects to the standard pick action.
22 | */
23 | public class PickWallpaper extends Wallpaper {
24 | }
25 |
--------------------------------------------------------------------------------
/res/anim/slide_in_vertical.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
22 |
--------------------------------------------------------------------------------
/res/anim/slide_out_vertical.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
22 |
--------------------------------------------------------------------------------
/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 | public class NoSearchActivity extends Activity {
22 | @Override
23 | public boolean onSearchRequested() {
24 | return false;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/res/anim/transition_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
25 |
--------------------------------------------------------------------------------
/res/anim/footer_appear.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
25 |
26 |
--------------------------------------------------------------------------------
/res/anim/footer_disappear.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
25 |
26 |
--------------------------------------------------------------------------------
/res/anim/transition_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
26 |
--------------------------------------------------------------------------------
/res/xml/appwidget_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
24 |
25 |
--------------------------------------------------------------------------------
/res/drawable/ic_menu_attach.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/res/drawable/ic_menu_cancel.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/res/drawable/grid_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/res/drawable/ic_menu_share.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/res/drawable/ic_menu_camera_play.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/res/drawable/ic_menu_delete.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/res/drawable/ic_menu_set_as.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/res/drawable/btn_camera_arrow_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
21 |
22 |
24 |
25 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/res/drawable/btn_camera_arrow_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
20 |
22 |
23 |
25 |
26 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/res/layout/delete_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
21 |
26 |
27 |
--------------------------------------------------------------------------------
/src/com/android/camera/GallerySettings.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 com.android.gallery.R;
20 |
21 | import android.os.Bundle;
22 | import android.preference.PreferenceActivity;
23 |
24 | // GallerySettings
25 | //
26 | // This is the setting screen for Gallery.
27 | // It reads the available settings from an XML resource.
28 | public class GallerySettings extends PreferenceActivity {
29 | @Override
30 | public void onCreate(Bundle icicle) {
31 | super.onCreate(icicle);
32 | addPreferencesFromResource(R.xml.gallery_preferences);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/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 | .includeAllPackagesUnderHere()
32 | .excludePackages("com.android.camera.stress")
33 | .named("Camera Unit Tests")
34 | .build();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/res/layout/custom_gallery_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
23 |
24 |
30 |
31 |
--------------------------------------------------------------------------------
/tests/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
28 |
29 |
32 |
33 |
--------------------------------------------------------------------------------
/res/drawable/frame_gallery_preview.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
21 |
22 |
24 |
25 |
27 |
28 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/res/layout/gallerypicker.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
21 |
33 |
34 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/res/layout/photo_frame.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
21 |
22 |
26 |
27 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/res/layout/gallery_picker_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
22 |
23 |
27 |
28 |
40 |
41 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
35 |
36 | #00000000
37 |
41 |
42 |
--------------------------------------------------------------------------------
/res/layout/gallerypicker_no_images.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
24 |
25 |
33 |
34 |
45 |
46 |
--------------------------------------------------------------------------------
/res/values-nl/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
19 |
20 | - "Groot"
21 | - "Klein"
22 |
23 |
24 | - "Nieuwste eerst"
25 | - "Nieuwste laatst"
26 |
27 |
28 | - "2 seconden"
29 | - "3 seconden"
30 | - "4 seconden"
31 |
32 |
33 | - "Infaden/uitfaden"
34 | - "Dia vanaf linkerkant/rechterkant"
35 | - "Dia vanaf bovenkant/onderkant"
36 | - "Willekeurige selectie"
37 |
38 |
39 |
--------------------------------------------------------------------------------
/res/layout/movie_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
21 |
22 |
26 |
27 |
32 |
33 |
38 |
39 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/com/android/camera/gallery/SingleImageList.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 | import java.util.HashMap;
23 |
24 | /**
25 | * An implementation of interface IImageList which contains only
26 | * one image.
27 | */
28 | public class SingleImageList implements IImageList {
29 |
30 | @SuppressWarnings("unused")
31 | private static final String TAG = "BaseImageList";
32 |
33 | private IImage mSingleImage;
34 | private Uri mUri;
35 |
36 | public SingleImageList(ContentResolver resolver, Uri uri) {
37 | mUri = uri;
38 | mSingleImage = new UriImage(this, resolver, uri);
39 | }
40 |
41 | public HashMap getBucketIds() {
42 | throw new UnsupportedOperationException();
43 | }
44 |
45 | public int getCount() {
46 | return 1;
47 | }
48 |
49 | public boolean isEmpty() {
50 | return false;
51 | }
52 |
53 | public int getImageIndex(IImage image) {
54 | return image == mSingleImage ? 0 : -1;
55 | }
56 |
57 | public IImage getImageAt(int i) {
58 | return i == 0 ? mSingleImage : null;
59 | }
60 |
61 | public boolean removeImage(IImage image) {
62 | return false;
63 | }
64 |
65 | public boolean removeImageAt(int index) {
66 | return false;
67 | }
68 |
69 | public IImage getImageForUri(Uri uri) {
70 | return uri.equals(mUri) ? mSingleImage : null;
71 | }
72 |
73 | public void close() {
74 | mSingleImage = null;
75 | mUri = null;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/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 |
47 | # ************************************************
48 | # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
49 | # ************************************************
50 |
--------------------------------------------------------------------------------
/res/layout/cropimage.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
20 |
21 |
25 |
26 |
33 |
40 |
47 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/tests/src/com/android/camera/gallery/LruCacheUnitTests.java:
--------------------------------------------------------------------------------
1 | package com.android.camera.gallery;
2 |
3 | import android.test.AndroidTestCase;
4 | import android.util.Log;
5 |
6 | public class LruCacheUnitTests extends AndroidTestCase {
7 |
8 | public void testPut() {
9 | LruCache cache = new LruCache(2);
10 | Integer key = Integer.valueOf(1);
11 | Integer value = Integer.valueOf(3);
12 | cache.put(key, value);
13 | assertEquals(value, cache.get(key));
14 | }
15 |
16 | public void testTracingInUsedObject() {
17 | LruCache cache = new LruCache(2);
18 | Integer key = Integer.valueOf(1);
19 | Integer value = new Integer(3);
20 | cache.put(key, value);
21 | for (int i = 0; i < 3; ++i) {
22 | cache.put(i + 10, i * i);
23 | }
24 | System.gc();
25 | assertEquals(value, cache.get(key));
26 | }
27 |
28 | public void testLruAlgorithm() {
29 | LruCache cache = new LruCache(2);
30 | cache.put(0, new Integer(0));
31 | for (int i = 0; i < 3; ++i) {
32 | cache.put(i + 1, i * i);
33 | cache.get(0);
34 | }
35 | System.gc();
36 | assertEquals(Integer.valueOf(0), cache.get(0));
37 | }
38 |
39 | private static final int TEST_COUNT = 10000;
40 |
41 | static class Accessor extends Thread {
42 | private final LruCache mMap;
43 |
44 | public Accessor(LruCache map) {
45 | mMap = map;
46 | }
47 |
48 | @Override
49 | public void run() {
50 | Log.v("TAG", "start get " + this);
51 | for (int i = 0; i < TEST_COUNT; ++i) {
52 | mMap.get(i % 2);
53 | }
54 | Log.v("TAG", "finish get " + this);
55 | }
56 | }
57 |
58 | @SuppressWarnings("unchecked")
59 | public void testConcurrentAccess() throws Exception {
60 | LruCache cache = new LruCache(4);
61 | cache.put(0, 0);
62 | cache.put(1, 1);
63 | Accessor accessor[] = new Accessor[4];
64 | for (int i = 0; i < accessor.length; ++i) {
65 | accessor[i] = new Accessor(cache);
66 | }
67 | for (int i = 0; i < accessor.length; ++i) {
68 | accessor[i].start();
69 | }
70 | for (int i = 0; i < accessor.length; ++i) {
71 | accessor[i].join();
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/com/android/camera/ReverseGeocoderTask.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.location.Address;
20 | import android.location.Geocoder;
21 | import android.os.AsyncTask;
22 | import android.util.Log;
23 |
24 | import java.io.IOException;
25 | import java.util.List;
26 |
27 | // Reverse geocoding may take a long time to return so we put it in AsyncTask.
28 | public class ReverseGeocoderTask extends AsyncTask {
29 | private static final String TAG = "ReverseGeocoder";
30 |
31 | public static interface Callback {
32 | public void onComplete(String location);
33 | }
34 |
35 | private Geocoder mGeocoder;
36 | private float mLat;
37 | private float mLng;
38 | private Callback mCallback;
39 |
40 | public ReverseGeocoderTask(Geocoder geocoder, float[] latlng,
41 | Callback callback) {
42 | mGeocoder = geocoder;
43 | mLat = latlng[0];
44 | mLng = latlng[1];
45 | mCallback = callback;
46 | }
47 |
48 | @Override
49 | protected String doInBackground(Void... params) {
50 | String value = MenuHelper.EMPTY_STRING;
51 | try {
52 | List address =
53 | mGeocoder.getFromLocation(mLat, mLng, 1);
54 | StringBuilder sb = new StringBuilder();
55 | for (Address addr : address) {
56 | int index = addr.getMaxAddressLineIndex();
57 | sb.append(addr.getAddressLine(index));
58 | }
59 | value = sb.toString();
60 | } catch (IOException ex) {
61 | value = MenuHelper.EMPTY_STRING;
62 | Log.e(TAG, "Geocoder exception: ", ex);
63 | } catch (RuntimeException ex) {
64 | value = MenuHelper.EMPTY_STRING;
65 | Log.e(TAG, "Geocoder exception: ", ex);
66 | }
67 | return value;
68 | }
69 |
70 | @Override
71 | protected void onPostExecute(String location) {
72 | mCallback.onComplete(location);
73 | }
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/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/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 | import android.net.Uri;
20 |
21 | import java.util.HashMap;
22 |
23 | //
24 | // ImageList and Image classes have one-to-one correspondence.
25 | // The class hierarchy (* = abstract class):
26 | //
27 | // IImageList
28 | // - BaseImageList (*)
29 | // - VideoList
30 | // - ImageList
31 | // - DrmImageList
32 | // - SingleImageList (contains UriImage)
33 | // - ImageListUber
34 | //
35 | // IImage
36 | // - BaseImage (*)
37 | // - VideoObject
38 | // - Image
39 | // - DrmImage
40 | // - UriImage
41 | //
42 |
43 | /**
44 | * The interface of all image collections used in gallery.
45 | */
46 | public interface IImageList {
47 | public HashMap getBucketIds();
48 |
49 | /**
50 | * Returns the count of image objects.
51 | *
52 | * @return the number of images
53 | */
54 | public int getCount();
55 |
56 | /**
57 | * @return true if the count of image objects is zero.
58 | */
59 | public boolean isEmpty();
60 |
61 | /**
62 | * Returns the image at the ith position.
63 | *
64 | * @param i the position
65 | * @return the image at the ith position
66 | */
67 | public IImage getImageAt(int i);
68 |
69 | /**
70 | * Returns the image with a particular Uri.
71 | *
72 | * @param uri
73 | * @return the image with a particular Uri. null if not found.
74 | */
75 | public IImage getImageForUri(Uri uri);
76 |
77 | /**
78 | *
79 | * @param image
80 | * @return true if the image was removed.
81 | */
82 | public boolean removeImage(IImage image);
83 |
84 | /**
85 | * Removes the image at the ith position.
86 | * @param i the position
87 | */
88 | public boolean removeImageAt(int i);
89 |
90 | public int getImageIndex(IImage image);
91 |
92 | /**
93 | * Closes this list to release resources, no further operation is allowed.
94 | */
95 | public void close();
96 | }
97 |
--------------------------------------------------------------------------------
/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 | public class LruCache {
26 |
27 | private final HashMap mLruMap;
28 | private final HashMap> mWeakMap =
29 | new HashMap>();
30 | private ReferenceQueue mQueue = new ReferenceQueue();
31 |
32 | @SuppressWarnings("serial")
33 | public LruCache(final int capacity) {
34 | mLruMap = new LinkedHashMap(16, 0.75f, true) {
35 | @Override
36 | protected boolean removeEldestEntry(Map.Entry eldest) {
37 | return size() > capacity;
38 | }
39 | };
40 | }
41 |
42 | private static class Entry extends WeakReference {
43 | K mKey;
44 |
45 | public Entry(K key, V value, ReferenceQueue queue) {
46 | super(value, queue);
47 | mKey = key;
48 | }
49 | }
50 |
51 | @SuppressWarnings("unchecked")
52 | private void cleanUpWeakMap() {
53 | Entry entry = (Entry) mQueue.poll();
54 | while (entry != null) {
55 | mWeakMap.remove(entry.mKey);
56 | entry = (Entry) mQueue.poll();
57 | }
58 | }
59 |
60 | public synchronized V put(K key, V value) {
61 | cleanUpWeakMap();
62 | mLruMap.put(key, value);
63 | Entry entry = mWeakMap.put(
64 | key, new Entry(key, value, mQueue));
65 | return entry == null ? null : entry.get();
66 | }
67 |
68 | public synchronized V get(K key) {
69 | cleanUpWeakMap();
70 | V value = mLruMap.get(key);
71 | if (value != null) return value;
72 | Entry entry = mWeakMap.get(key);
73 | return entry == null ? null : entry.get();
74 | }
75 |
76 | public synchronized void clear() {
77 | mLruMap.clear();
78 | mWeakMap.clear();
79 | mQueue = new ReferenceQueue();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/com/android/camera/Wallpaper.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.Intent;
20 | import android.net.Uri;
21 | import android.os.Bundle;
22 |
23 | /**
24 | * Wallpaper picker for the camera application. This just redirects to the
25 | * standard pick action.
26 | */
27 | public class Wallpaper extends NoSearchActivity {
28 | @SuppressWarnings("unused")
29 | private static final String TAG = "Wallpaper";
30 | private static final int PHOTO_PICKED = 1;
31 | private static final int CROP_DONE = 2;
32 |
33 | @Override
34 | protected void onCreate(Bundle icicle) {
35 | super.onCreate(icicle);
36 |
37 | Uri imageToUse = getIntent().getData();
38 | if (imageToUse != null) {
39 | Intent intent = new Intent();
40 | intent.setClass(this, CropImage.class);
41 | intent.setData(imageToUse);
42 | formatIntent(intent);
43 | startActivityForResult(intent, CROP_DONE);
44 | } else {
45 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
46 | intent.setType("image/*");
47 | intent.putExtra("crop", "true");
48 | formatIntent(intent);
49 | startActivityForResult(intent, PHOTO_PICKED);
50 | }
51 | }
52 |
53 | protected void formatIntent(Intent intent) {
54 | int width = getWallpaperDesiredMinimumWidth();
55 | int height = getWallpaperDesiredMinimumHeight();
56 | intent.putExtra("outputX", width);
57 | intent.putExtra("outputY", height);
58 | intent.putExtra("aspectX", width);
59 | intent.putExtra("aspectY", height);
60 | intent.putExtra("scale", true);
61 | intent.putExtra("noFaceDetection", true);
62 | intent.putExtra("setWallpaper", true);
63 | }
64 |
65 | @Override
66 | protected void onActivityResult(int requestCode, int resultCode,
67 | Intent data) {
68 | if ((requestCode == PHOTO_PICKED || requestCode == CROP_DONE)) {
69 | setResult(resultCode);
70 | finish();
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/com/android/camera/DeleteImage.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.gallery.R;
20 |
21 | import android.app.Activity;
22 | import android.content.ContentResolver;
23 | import android.content.Intent;
24 | import android.net.Uri;
25 | import android.os.Bundle;
26 | import android.os.Handler;
27 | import android.widget.ProgressBar;
28 |
29 | import java.util.ArrayList;
30 |
31 | public class DeleteImage extends NoSearchActivity {
32 |
33 | @SuppressWarnings("unused")
34 | private static final String TAG = "DeleteImage";
35 | private ProgressBar mProgressBar;
36 | private ArrayList mUriList; // a list of image uri
37 | private int mIndex = 0; // next image to delete
38 | private final Handler mHandler = new Handler();
39 | private final Runnable mDeleteNextRunnable = new Runnable() {
40 | public void run() {
41 | deleteNext();
42 | }
43 | };
44 | private ContentResolver mContentResolver;
45 | private boolean mPausing;
46 |
47 | @Override
48 | protected void onCreate(Bundle savedInstanceState) {
49 | super.onCreate(savedInstanceState);
50 | Intent intent = getIntent();
51 | mUriList = intent.getParcelableArrayListExtra("delete-uris");
52 | if (mUriList == null) {
53 | finish();
54 | }
55 | setContentView(R.layout.delete_image);
56 | mProgressBar = (ProgressBar) findViewById(R.id.delete_progress);
57 | mContentResolver = getContentResolver();
58 | }
59 |
60 | @Override
61 | protected void onResume() {
62 | super.onResume();
63 | mPausing = false;
64 | mHandler.post(mDeleteNextRunnable);
65 | }
66 |
67 | private void deleteNext() {
68 | if (mPausing) return;
69 | if (mIndex >= mUriList.size()) {
70 | finish();
71 | return;
72 | }
73 | Uri uri = mUriList.get(mIndex++);
74 | // The max progress value of the bar is set to 10000 in the xml file.
75 | mProgressBar.setProgress(mIndex * 10000 / mUriList.size());
76 | mContentResolver.delete(uri, null, null);
77 | mHandler.post(mDeleteNextRunnable);
78 | }
79 |
80 | @Override
81 | protected void onPause() {
82 | super.onPause();
83 | mPausing = true;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/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 | import java.io.InputStream;
23 |
24 | /**
25 | * The interface of all images used in gallery.
26 | */
27 | public interface IImage {
28 | static final int THUMBNAIL_TARGET_SIZE = 320;
29 | static final int MINI_THUMB_TARGET_SIZE = 96;
30 | static final int THUMBNAIL_MAX_NUM_PIXELS = 512 * 384;
31 | static final int MINI_THUMB_MAX_NUM_PIXELS = 128 * 128;
32 | static final int UNCONSTRAINED = -1;
33 |
34 | /** Get the image list which contains this image. */
35 | public abstract IImageList getContainer();
36 |
37 | /** Get the bitmap for the full size image. */
38 | public abstract Bitmap fullSizeBitmap(int minSideLength,
39 | int maxNumberOfPixels);
40 | public abstract Bitmap fullSizeBitmap(int minSideLength,
41 | int maxNumberOfPixels, boolean rotateAsNeeded, boolean useNative);
42 | public abstract int getDegreesRotated();
43 | public static final boolean ROTATE_AS_NEEDED = true;
44 | public static final boolean NO_ROTATE = false;
45 | public static final boolean USE_NATIVE = true;
46 | public static final boolean NO_NATIVE = false;
47 |
48 | /** Get the input stream associated with a given full size image. */
49 | public abstract InputStream fullSizeImageData();
50 | public abstract Uri fullSizeImageUri();
51 |
52 | /** Get the path of the (full size) image data. */
53 | public abstract String getDataPath();
54 |
55 | // Get the title of the image
56 | public abstract String getTitle();
57 |
58 | // Get metadata of the image
59 | public abstract long getDateTaken();
60 |
61 | public abstract String getMimeType();
62 |
63 | public abstract int getWidth();
64 |
65 | public abstract int getHeight();
66 |
67 | // Get property of the image
68 | public abstract boolean isReadonly();
69 | public abstract boolean isDrm();
70 |
71 | // Get the bitmap of the medium thumbnail
72 | public abstract Bitmap thumbBitmap(boolean rotateAsNeeded);
73 |
74 | // Get the bitmap of the mini thumbnail.
75 | public abstract Bitmap miniThumbBitmap();
76 |
77 | // Rotate the image
78 | public abstract boolean rotateImageBy(int degrees);
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/com/android/camera/RotateBitmap.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.graphics.Bitmap;
20 | import android.graphics.Matrix;
21 |
22 | public class RotateBitmap {
23 | public static final String TAG = "RotateBitmap";
24 | private Bitmap mBitmap;
25 | private int mRotation;
26 |
27 | public RotateBitmap(Bitmap bitmap) {
28 | mBitmap = bitmap;
29 | mRotation = 0;
30 | }
31 |
32 | public RotateBitmap(Bitmap bitmap, int rotation) {
33 | mBitmap = bitmap;
34 | mRotation = rotation % 360;
35 | }
36 |
37 | public void setRotation(int rotation) {
38 | mRotation = rotation;
39 | }
40 |
41 | public int getRotation() {
42 | return mRotation;
43 | }
44 |
45 | public Bitmap getBitmap() {
46 | return mBitmap;
47 | }
48 |
49 | public void setBitmap(Bitmap bitmap) {
50 | mBitmap = bitmap;
51 | }
52 |
53 | public Matrix getRotateMatrix() {
54 | // By default this is an identity matrix.
55 | Matrix matrix = new Matrix();
56 | if (mRotation != 0) {
57 | // We want to do the rotation at origin, but since the bounding
58 | // rectangle will be changed after rotation, so the delta values
59 | // are based on old & new width/height respectively.
60 | int cx = mBitmap.getWidth() / 2;
61 | int cy = mBitmap.getHeight() / 2;
62 | matrix.preTranslate(-cx, -cy);
63 | matrix.postRotate(mRotation);
64 | matrix.postTranslate(getWidth() / 2, getHeight() / 2);
65 | }
66 | return matrix;
67 | }
68 |
69 | public boolean isOrientationChanged() {
70 | return (mRotation / 90) % 2 != 0;
71 | }
72 |
73 | public int getHeight() {
74 | if (isOrientationChanged()) {
75 | return mBitmap.getWidth();
76 | } else {
77 | return mBitmap.getHeight();
78 | }
79 | }
80 |
81 | public int getWidth() {
82 | if (isOrientationChanged()) {
83 | return mBitmap.getHeight();
84 | } else {
85 | return mBitmap.getWidth();
86 | }
87 | }
88 |
89 | public void recycle() {
90 | if (mBitmap != null) {
91 | mBitmap.recycle();
92 | mBitmap = null;
93 | }
94 | }
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/src/com/android/camera/MonitoredActivity.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.os.Bundle;
21 |
22 | import java.util.ArrayList;
23 |
24 | public class MonitoredActivity extends NoSearchActivity {
25 |
26 | private final ArrayList mListeners =
27 | new ArrayList();
28 |
29 | public static interface LifeCycleListener {
30 | public void onActivityCreated(MonitoredActivity activity);
31 | public void onActivityDestroyed(MonitoredActivity activity);
32 | public void onActivityStarted(MonitoredActivity activity);
33 | public void onActivityStopped(MonitoredActivity activity);
34 | }
35 |
36 | public static class LifeCycleAdapter implements LifeCycleListener {
37 | public void onActivityCreated(MonitoredActivity activity) {
38 | }
39 |
40 | public void onActivityDestroyed(MonitoredActivity activity) {
41 | }
42 |
43 | public void onActivityStarted(MonitoredActivity activity) {
44 | }
45 |
46 | public void onActivityStopped(MonitoredActivity activity) {
47 | }
48 | }
49 |
50 | public void addLifeCycleListener(LifeCycleListener listener) {
51 | if (mListeners.contains(listener)) return;
52 | mListeners.add(listener);
53 | }
54 |
55 | public void removeLifeCycleListener(LifeCycleListener listener) {
56 | mListeners.remove(listener);
57 | }
58 |
59 | @Override
60 | protected void onCreate(Bundle savedInstanceState) {
61 | super.onCreate(savedInstanceState);
62 | for (LifeCycleListener listener : mListeners) {
63 | listener.onActivityCreated(this);
64 | }
65 | }
66 |
67 | @Override
68 | protected void onDestroy() {
69 | super.onDestroy();
70 | for (LifeCycleListener listener : mListeners) {
71 | listener.onActivityDestroyed(this);
72 | }
73 | }
74 |
75 | @Override
76 | protected void onStart() {
77 | super.onStart();
78 | for (LifeCycleListener listener : mListeners) {
79 | listener.onActivityStarted(this);
80 | }
81 | }
82 |
83 | @Override
84 | protected void onStop() {
85 | super.onStop();
86 | for (LifeCycleListener listener : mListeners) {
87 | listener.onActivityStopped(this);
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/com/android/camera/PhotoAppWidgetBind.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.PhotoAppWidgetProvider.PhotoDatabaseHelper;
20 |
21 | import android.app.Activity;
22 | import android.appwidget.AppWidgetManager;
23 | import android.content.Intent;
24 | import android.graphics.Bitmap;
25 | import android.os.Bundle;
26 | import android.util.Log;
27 | import android.widget.RemoteViews;
28 |
29 | import java.util.ArrayList;
30 |
31 | class PhotoAppWidgetBind extends NoSearchActivity {
32 | private static final String TAG = "PhotoAppWidgetBind";
33 | private static final String EXTRA_APPWIDGET_BITMAPS =
34 | "com.android.camera.appwidgetbitmaps";
35 |
36 | @Override
37 | protected void onCreate(Bundle icicle) {
38 | super.onCreate(icicle);
39 | finish();
40 |
41 | // The caller has requested that we bind a given bitmap to a specific
42 | // appWidgetId, which probably is happening during a Launcher upgrade.
43 | // This is dangerous because the caller could set bitmaps on
44 | // appWidgetIds they don't own, so we guard this call at the manifest
45 | // level by requiring the BIND_APPWIDGET permission.
46 |
47 | final Intent intent = getIntent();
48 | final Bundle extras = intent.getExtras();
49 |
50 | final int[] appWidgetIds =
51 | extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
52 | final ArrayList bitmaps =
53 | extras.getParcelableArrayList(EXTRA_APPWIDGET_BITMAPS);
54 |
55 | if (appWidgetIds == null || bitmaps == null
56 | || appWidgetIds.length != bitmaps.size()) {
57 | Log.e(TAG, "Problem parsing photo widget bind request");
58 | return;
59 | }
60 |
61 | AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
62 | PhotoDatabaseHelper helper = new PhotoDatabaseHelper(this);
63 | for (int i = 0; i < appWidgetIds.length; i++) {
64 | // Store the cropped photo in our database
65 | int appWidgetId = appWidgetIds[i];
66 | helper.setPhoto(appWidgetId, bitmaps.get(i));
67 |
68 | // Push newly updated widget to surface
69 | RemoteViews views =
70 | PhotoAppWidgetProvider.buildUpdate(this, appWidgetId,
71 | helper);
72 | appWidgetManager.updateAppWidget(new int[] { appWidgetId }, views);
73 | }
74 | helper.close();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/com/android/camera/ActionMenuButton.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 com.android.gallery.R;
20 |
21 | import android.content.Context;
22 | import android.graphics.Canvas;
23 | import android.graphics.Paint;
24 | import android.graphics.RectF;
25 | import android.text.Layout;
26 | import android.util.AttributeSet;
27 | import android.widget.TextView;
28 |
29 | /**
30 | * TextView that draws a bubble behind the text. We cannot use a
31 | * LineBackgroundSpan because we want to make the bubble taller than the text
32 | * and TextView's clip is too aggressive.
33 | */
34 | public class ActionMenuButton extends TextView {
35 | private static final int CORNER_RADIUS = 8;
36 | private static final int PADDING_H = 5;
37 | private static final int PADDING_V = 1;
38 |
39 | private final RectF mRect = new RectF();
40 | private Paint mPaint;
41 |
42 | public ActionMenuButton(Context context) {
43 | super(context);
44 | init();
45 | }
46 |
47 | public ActionMenuButton(Context context, AttributeSet attrs) {
48 | super(context, attrs);
49 | init();
50 | }
51 |
52 | public ActionMenuButton(Context context, AttributeSet attrs, int defStyle) {
53 | super(context, attrs, defStyle);
54 | init();
55 | }
56 |
57 | private void init() {
58 | setFocusable(true);
59 | // We need extra padding below to prevent the bubble being cut.
60 | setPadding(PADDING_H, 0, PADDING_H, PADDING_V);
61 |
62 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
63 | mPaint.setColor(getContext().getResources()
64 | .getColor(R.color.bubble_dark_background));
65 | }
66 |
67 | @Override
68 | protected void drawableStateChanged() {
69 | invalidate();
70 | super.drawableStateChanged();
71 | }
72 |
73 | @Override
74 | public void draw(Canvas canvas) {
75 | final Layout layout = getLayout();
76 | final RectF rect = mRect;
77 | final int left = getCompoundPaddingLeft();
78 | final int top = getExtendedPaddingTop();
79 |
80 | rect.set(left + layout.getLineLeft(0) - PADDING_H,
81 | top + layout.getLineTop(0) - PADDING_V,
82 | Math.min(left + layout.getLineRight(0) + PADDING_H,
83 | mScrollX + mRight - mLeft),
84 | top + layout.getLineBottom(0) + PADDING_V);
85 | canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, mPaint);
86 |
87 | super.draw(canvas);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/com/android/camera/MovieView.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 com.android.gallery.R;
20 |
21 |
22 | import android.app.Activity;
23 | import android.content.Intent;
24 | import android.content.pm.ActivityInfo;
25 | import android.os.Bundle;
26 | import android.provider.MediaStore;
27 | import android.util.Log;
28 | import android.view.View;
29 |
30 | /**
31 | * This activity plays a video from a specified URI.
32 | */
33 | public class MovieView extends NoSearchActivity {
34 | private static final String TAG = "MovieView";
35 |
36 | private MovieViewControl mControl;
37 | private boolean mFinishOnCompletion;
38 | private boolean mResumed = false; // Whether this activity has been resumed.
39 | private boolean mFocused = false; // Whether this window has focus.
40 | private boolean mControlResumed = false; // Whether the MovieViewControl is resumed.
41 |
42 | @Override
43 | public void onCreate(Bundle icicle) {
44 | super.onCreate(icicle);
45 | setContentView(R.layout.movie_view);
46 | View rootView = findViewById(R.id.root);
47 | Intent intent = getIntent();
48 | mControl = new MovieViewControl(rootView, this, intent.getData()) {
49 | @Override
50 | public void onCompletion() {
51 | if (mFinishOnCompletion) {
52 | finish();
53 | }
54 | }
55 | };
56 | if (intent.hasExtra(MediaStore.EXTRA_SCREEN_ORIENTATION)) {
57 | int orientation = intent.getIntExtra(
58 | MediaStore.EXTRA_SCREEN_ORIENTATION,
59 | ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
60 | if (orientation != getRequestedOrientation()) {
61 | setRequestedOrientation(orientation);
62 | }
63 | }
64 | mFinishOnCompletion = intent.getBooleanExtra(
65 | MediaStore.EXTRA_FINISH_ON_COMPLETION, true);
66 | }
67 |
68 | @Override
69 | public void onPause() {
70 | super.onPause();
71 | mResumed = false;
72 | if (mControlResumed) {
73 | mControl.onPause();
74 | mControlResumed = false;
75 | }
76 | }
77 |
78 | @Override
79 | public void onResume() {
80 | super.onResume();
81 | mResumed = true;
82 | if (mFocused && mResumed && !mControlResumed) {
83 | mControl.onResume();
84 | mControlResumed = true;
85 | }
86 | }
87 |
88 | @Override
89 | public void onWindowFocusChanged(boolean hasFocus) {
90 | mFocused = hasFocus;
91 | if (mFocused && mResumed && !mControlResumed) {
92 | mControl.onResume();
93 | mControlResumed = true;
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/com/android/camera/GalleryPickerItem.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 com.android.gallery.R;
20 |
21 | import android.content.Context;
22 | import android.graphics.Canvas;
23 | import android.graphics.Rect;
24 | import android.graphics.drawable.Drawable;
25 | import android.util.AttributeSet;
26 | import android.widget.ImageView;
27 |
28 | class GalleryPickerItem extends ImageView {
29 | private Drawable mFrame;
30 | private Rect mFrameBounds = new Rect();
31 | private Drawable mOverlay;
32 |
33 | public GalleryPickerItem(Context context) {
34 | this(context, null);
35 | }
36 |
37 | public GalleryPickerItem(Context context, AttributeSet attrs) {
38 | this(context, attrs, 0);
39 | }
40 |
41 | public GalleryPickerItem(Context context,
42 | AttributeSet attrs,
43 | int defStyle) {
44 | super(context, attrs, defStyle);
45 |
46 | mFrame = getResources().getDrawable(R.drawable.frame_gallery_preview);
47 | mFrame.setCallback(this);
48 | }
49 |
50 | @Override
51 | protected boolean verifyDrawable(Drawable who) {
52 | return super.verifyDrawable(who) || (who == mFrame)
53 | || (who == mOverlay);
54 | }
55 |
56 | @Override
57 | protected void drawableStateChanged() {
58 | super.drawableStateChanged();
59 | if (mFrame != null) {
60 | int[] drawableState = getDrawableState();
61 | mFrame.setState(drawableState);
62 | }
63 | }
64 |
65 | @Override
66 | protected void onDraw(Canvas canvas) {
67 | super.onDraw(canvas);
68 | final Rect frameBounds = mFrameBounds;
69 | if (frameBounds.isEmpty()) {
70 | final int w = getWidth();
71 | final int h = getHeight();
72 |
73 | frameBounds.set(0, 0, w, h);
74 | mFrame.setBounds(frameBounds);
75 | if (mOverlay != null) {
76 | mOverlay.setBounds(w - mOverlay.getIntrinsicWidth(),
77 | h - mOverlay.getIntrinsicHeight(), w, h);
78 | }
79 | }
80 |
81 | mFrame.draw(canvas);
82 | if (mOverlay != null) {
83 | mOverlay.draw(canvas);
84 | }
85 | }
86 |
87 |
88 | @Override
89 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
90 | super.onSizeChanged(w, h, oldw, oldh);
91 |
92 | mFrameBounds.setEmpty();
93 | }
94 |
95 | public void setOverlay(int overlayId) {
96 | if (overlayId >= 0) {
97 | mOverlay = getResources().getDrawable(overlayId);
98 | mFrameBounds.setEmpty();
99 | } else {
100 | mOverlay = null;
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/com/android/camera/gallery/DrmImageList.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.graphics.Bitmap;
22 | import android.net.Uri;
23 | import android.provider.DrmStore;
24 |
25 | /**
26 | * Represents an ordered collection of Image objects from the DRM provider.
27 | */
28 | public class DrmImageList extends ImageList implements IImageList {
29 |
30 | // TODO: get other field from database too ?
31 | private static final String[] DRM_IMAGE_PROJECTION = new String[] {
32 | DrmStore.Images._ID,
33 | DrmStore.Images.DATA,
34 | DrmStore.Images.MIME_TYPE,
35 | };
36 |
37 | private static final int INDEX_ID = 0;
38 | private static final int INDEX_DATA_PATH = 1;
39 | private static final int INDEX_MIME_TYPE = 2;
40 |
41 | public DrmImageList(ContentResolver resolver, Uri imageUri, int sort,
42 | String bucketId) {
43 | super(resolver, imageUri, sort, bucketId);
44 | }
45 |
46 | @Override
47 | protected String sortOrder() {
48 | // We have no date information in DrmStore, so we just sort by _id.
49 | return "_id ASC";
50 | }
51 |
52 | @Override
53 | protected Cursor createCursor() {
54 | return mContentResolver.query(
55 | mBaseUri, DRM_IMAGE_PROJECTION, null, null, sortOrder());
56 | }
57 |
58 | private static class DrmImage extends Image {
59 |
60 | protected DrmImage(BaseImageList container, ContentResolver cr,
61 | long id, int index, Uri uri, String dataPath,
62 | long miniThumbMagic, String mimeType, long dateTaken,
63 | String title, int rotation) {
64 | super(container, cr, id, index, uri, dataPath,
65 | mimeType, dateTaken, title, rotation);
66 | }
67 |
68 | @Override
69 | public int getDegreesRotated() {
70 | return 0;
71 | }
72 |
73 | @Override
74 | public boolean isDrm() {
75 | return true;
76 | }
77 |
78 | @Override
79 | public boolean isReadonly() {
80 | return true;
81 | }
82 |
83 | @Override
84 | public Bitmap miniThumbBitmap() {
85 | return fullSizeBitmap(IImage.MINI_THUMB_TARGET_SIZE,
86 | IImage.MINI_THUMB_MAX_NUM_PIXELS);
87 | }
88 |
89 | @Override
90 | public Bitmap thumbBitmap(boolean rotateAsNeeded) {
91 | return fullSizeBitmap(IImage.THUMBNAIL_TARGET_SIZE,
92 | IImage.THUMBNAIL_MAX_NUM_PIXELS);
93 | }
94 | }
95 |
96 | @Override
97 | protected BaseImage loadImageFromCursor(Cursor cursor) {
98 | long id = cursor.getLong(INDEX_ID);
99 | String dataPath = cursor.getString(INDEX_DATA_PATH);
100 | String mimeType = cursor.getString(INDEX_MIME_TYPE);
101 | return new DrmImage(this, mContentResolver, id, cursor.getPosition(),
102 | contentUri(id), dataPath, 0, mimeType, 0, "DrmImage-" + id,
103 | 0);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/tests/src/com/android/camera/gallery/ImageListUberUnitTests.java:
--------------------------------------------------------------------------------
1 | package com.android.camera.gallery;
2 |
3 | import com.android.camera.ImageManager;
4 |
5 | import android.test.AndroidTestCase;
6 |
7 | public class ImageListUberUnitTests extends AndroidTestCase {
8 |
9 | private MockImage getImageAt(ImageListUber uber, int index) {
10 | return (MockImage) uber.getImageAt(index);
11 | }
12 |
13 | public void testTheOrderOfGetImageAt() {
14 | MockImageList listA = new MockImageList();
15 | MockImageList listB = new MockImageList();
16 | listA.addImage(new MockImage(2, 2));
17 | listA.addImage(new MockImage(0, 0));
18 | listB.addImage(new MockImage(1, 1));
19 | ImageListUber uber = new ImageListUber(
20 | new IImageList[] {listA, listB}, ImageManager.SORT_DESCENDING);
21 |
22 | assertEquals(2, getImageAt(uber, 0).fullSizeImageId());
23 | assertEquals(1, getImageAt(uber, 1).fullSizeImageId());
24 | assertEquals(0, getImageAt(uber, 2).fullSizeImageId());
25 | uber.close();
26 |
27 | uber = new ImageListUber(
28 | new IImageList[] {listA, listB}, ImageManager.SORT_DESCENDING);
29 | assertEquals(2, getImageAt(uber, 0).fullSizeImageId());
30 | assertEquals(1, getImageAt(uber, 1).fullSizeImageId());
31 | assertEquals(0, getImageAt(uber, 2).fullSizeImageId());
32 | uber.close();
33 | }
34 |
35 | public void testTheOrderOfGetImageAtCaseTwo() {
36 | MockImageList listA = new MockImageList();
37 | MockImageList listB = new MockImageList();
38 | listA.addImage(new MockImage(2, 2));
39 | listA.addImage(new MockImage(1, 1));
40 | listB.addImage(new MockImage(0, 0));
41 | ImageListUber uber = new ImageListUber(
42 | new IImageList[] {listB, listA}, ImageManager.SORT_DESCENDING);
43 |
44 | assertEquals(2, getImageAt(uber, 0).fullSizeImageId());
45 | assertEquals(1, getImageAt(uber, 1).fullSizeImageId());
46 | assertEquals(0, getImageAt(uber, 2).fullSizeImageId());
47 | uber.close();
48 |
49 | uber = new ImageListUber(
50 | new IImageList[] {listA, listB}, ImageManager.SORT_DESCENDING);
51 |
52 | assertEquals(2, getImageAt(uber, 0).fullSizeImageId());
53 | assertEquals(1, getImageAt(uber, 1).fullSizeImageId());
54 | assertEquals(0, getImageAt(uber, 2).fullSizeImageId());
55 | uber.close();
56 | }
57 |
58 | public void testRemoveImage() {
59 | MockImageList listA = new MockImageList();
60 | MockImageList listB = new MockImageList();
61 | MockImage target = new MockImage(1, 1);
62 | listA.addImage(new MockImage(2, 2));
63 | listA.addImage(new MockImage(0, 0));
64 | listB.addImage(target);
65 | ImageListUber uber = new ImageListUber(
66 | new IImageList[] {listB, listA}, ImageManager.SORT_DESCENDING);
67 | uber.removeImage(target);
68 | assertEquals(2, getImageAt(uber, 0).fullSizeImageId());
69 | assertEquals(0, getImageAt(uber, 1).fullSizeImageId());
70 |
71 | assertEquals(0, uber.getImageIndex(getImageAt(uber, 0)));
72 | assertEquals(1, uber.getImageIndex(getImageAt(uber, 1)));
73 | uber.close();
74 | }
75 |
76 | public void testRemoveImageAt() {
77 | MockImageList listA = new MockImageList();
78 | MockImageList listB = new MockImageList();
79 | MockImage target = new MockImage(1, 1);
80 | listA.addImage(new MockImage(2, 2));
81 | listA.addImage(new MockImage(0, 0));
82 | listB.addImage(target);
83 | ImageListUber uber = new ImageListUber(
84 | new IImageList[] {listB, listA}, ImageManager.SORT_DESCENDING);
85 | uber.removeImageAt(1);
86 | assertEquals(2, getImageAt(uber, 0).fullSizeImageId());
87 | assertEquals(0, getImageAt(uber, 1).fullSizeImageId());
88 |
89 | assertEquals(0, uber.getImageIndex(getImageAt(uber, 0)));
90 | assertEquals(1, uber.getImageIndex(getImageAt(uber, 1)));
91 | uber.close();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/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.media.ThumbnailUtils;
24 | import android.net.Uri;
25 | import android.provider.MediaStore.Images;
26 | import android.provider.MediaStore.Video;
27 | import android.util.Log;
28 |
29 | import java.io.IOException;
30 | import java.io.InputStream;
31 |
32 | /**
33 | * Represents a particular video and provides access to the underlying data and
34 | * two thumbnail bitmaps as well as other information such as the id, and the
35 | * path to the actual video data.
36 | */
37 | public class VideoObject extends BaseImage implements IImage {
38 | private static final String TAG = "VideoObject";
39 | /**
40 | * Constructor.
41 | *
42 | * @param id the image id of the image
43 | * @param cr the content resolver
44 | */
45 | protected VideoObject(BaseImageList container, ContentResolver cr,
46 | long id, int index, Uri uri, String dataPath,
47 | String mimeType, long dateTaken, String title) {
48 | super(container, cr, id, index, uri, dataPath,
49 | mimeType, dateTaken, title);
50 | }
51 |
52 | @Override
53 | public boolean equals(Object other) {
54 | if (other == null || !(other instanceof VideoObject)) return false;
55 | return fullSizeImageUri().equals(
56 | ((VideoObject) other).fullSizeImageUri());
57 | }
58 |
59 | @Override
60 | public int hashCode() {
61 | return fullSizeImageUri().toString().hashCode();
62 | }
63 |
64 | @Override
65 | public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels,
66 | boolean rotateAsNeeded, boolean useNative) {
67 | return ThumbnailUtils.createVideoThumbnail(mDataPath,
68 | Video.Thumbnails.MINI_KIND);
69 | }
70 |
71 | @Override
72 | public InputStream fullSizeImageData() {
73 | try {
74 | InputStream input = mContentResolver.openInputStream(
75 | fullSizeImageUri());
76 | return input;
77 | } catch (IOException ex) {
78 | return null;
79 | }
80 | }
81 |
82 | @Override
83 | public int getHeight() {
84 | return 0;
85 | }
86 |
87 | @Override
88 | public int getWidth() {
89 | return 0;
90 | }
91 |
92 | public boolean isReadonly() {
93 | return false;
94 | }
95 |
96 | public boolean isDrm() {
97 | return false;
98 | }
99 |
100 | public boolean rotateImageBy(int degrees) {
101 | return false;
102 | }
103 |
104 | public Bitmap thumbBitmap(boolean rotateAsNeeded) {
105 | return fullSizeBitmap(THUMBNAIL_TARGET_SIZE, THUMBNAIL_MAX_NUM_PIXELS);
106 | }
107 |
108 | @Override
109 | public Bitmap miniThumbBitmap() {
110 | try {
111 | long id = mId;
112 | return BitmapManager.instance().getThumbnail(mContentResolver,
113 | id, Images.Thumbnails.MICRO_KIND, null, true);
114 | } catch (Throwable ex) {
115 | Log.e(TAG, "miniThumbBitmap got exception", ex);
116 | return null;
117 | }
118 | }
119 |
120 | @Override
121 | public String toString() {
122 | return new StringBuilder("VideoObject").append(mId).toString();
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/res/layout/image_gallery.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
20 |
21 |
24 |
25 |
33 |
34 |
46 |
47 |
52 |
53 |
58 |
59 |
64 |
65 |
66 |
67 |
73 |
74 |
82 |
83 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/src/com/android/camera/PhotoAppWidgetConfigure.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.PhotoAppWidgetProvider.PhotoDatabaseHelper;
20 |
21 | import android.app.Activity;
22 | import android.appwidget.AppWidgetManager;
23 | import android.content.Intent;
24 | import android.graphics.Bitmap;
25 | import android.os.Bundle;
26 | import android.util.DisplayMetrics;
27 | import android.widget.RemoteViews;
28 |
29 | public class PhotoAppWidgetConfigure extends NoSearchActivity {
30 |
31 | @SuppressWarnings("unused")
32 | private static final String TAG = "PhotoAppWidgetConfigure";
33 | static final int REQUEST_GET_PHOTO = 2;
34 |
35 | int mAppWidgetId = -1;
36 |
37 | @Override
38 | protected void onCreate(Bundle icicle) {
39 | super.onCreate(icicle);
40 |
41 | // Someone is requesting that we configure the given mAppWidgetId, which
42 | // means we prompt the user to pick and crop a photo.
43 |
44 | mAppWidgetId = getIntent().getIntExtra(
45 | AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
46 | if (mAppWidgetId == -1) {
47 | setResult(Activity.RESULT_CANCELED);
48 | finish();
49 | }
50 |
51 | // Assume the widget will be 1/4 of the screen.
52 | // This will be slightly too large, but there is not a good way to know the
53 | // actual widget size from here. The image will be scaled to fit since the layout
54 | // file specifies android:scaleType="centerCrop"
55 | DisplayMetrics display = getResources().getDisplayMetrics();
56 | int maxDimension = Math.max(display.heightPixels, display.widthPixels);
57 | maxDimension /= 2;
58 |
59 | // TODO: Adjust the PhotoFrame's image size to avoid on the fly scaling
60 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
61 | intent.setType("image/*");
62 | intent.putExtra("crop", "true");
63 | intent.putExtra("aspectX", 1);
64 | intent.putExtra("aspectY", 1);
65 | intent.putExtra("outputX", maxDimension);
66 | intent.putExtra("outputY", maxDimension);
67 | intent.putExtra("noFaceDetection", true);
68 | intent.putExtra("return-data", true);
69 |
70 | startActivityForResult(intent, REQUEST_GET_PHOTO);
71 | }
72 |
73 | @Override
74 | protected void onActivityResult(int requestCode, int resultCode,
75 | Intent data) {
76 | if (resultCode == RESULT_OK && mAppWidgetId != -1) {
77 | // Store the cropped photo in our database
78 | Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");
79 |
80 | PhotoDatabaseHelper helper = new PhotoDatabaseHelper(this);
81 | if (helper.setPhoto(mAppWidgetId, bitmap)) {
82 | resultCode = Activity.RESULT_OK;
83 |
84 | // Push newly updated widget to surface
85 | RemoteViews views = PhotoAppWidgetProvider.buildUpdate(this,
86 | mAppWidgetId, helper);
87 | AppWidgetManager appWidgetManager =
88 | AppWidgetManager.getInstance(this);
89 | appWidgetManager.updateAppWidget(new int[] {mAppWidgetId},
90 | views);
91 | }
92 | helper.close();
93 | } else {
94 | resultCode = Activity.RESULT_CANCELED;
95 | }
96 |
97 | // Make sure we pass back the original mAppWidgetId
98 | Intent resultValue = new Intent();
99 | resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
100 | setResult(resultCode, resultValue);
101 | finish();
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/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 | import java.util.HashMap;
26 |
27 | /**
28 | * A collection of all the VideoObject in gallery.
29 | */
30 | public class VideoList extends BaseImageList {
31 |
32 | @SuppressWarnings("unused")
33 | private static final String TAG = "BaseImageList";
34 |
35 | private static final String[] VIDEO_PROJECTION = new String[] {
36 | Media._ID,
37 | Media.DATA,
38 | Media.DATE_TAKEN,
39 | Media.TITLE,
40 | Media.MINI_THUMB_MAGIC,
41 | Media.MIME_TYPE,
42 | Media.DATE_MODIFIED};
43 |
44 | private static final int INDEX_ID = 0;
45 | private static final int INDEX_DATA_PATH = 1;
46 | private static final int INDEX_DATE_TAKEN = 2;
47 | private static final int INDEX_TITLE = 3;
48 | private static final int INDEX_MIMI_THUMB_MAGIC = 4;
49 | private static final int INDEX_MIME_TYPE = 5;
50 | private static final int INDEX_DATE_MODIFIED = 6;
51 |
52 | @Override
53 | protected long getImageId(Cursor cursor) {
54 | return cursor.getLong(INDEX_ID);
55 | }
56 |
57 | @Override
58 | protected BaseImage loadImageFromCursor(Cursor cursor) {
59 | long id = cursor.getLong(INDEX_ID);
60 | String dataPath = cursor.getString(INDEX_DATA_PATH);
61 | long dateTaken = cursor.getLong(INDEX_DATE_TAKEN);
62 | if (dateTaken == 0) {
63 | dateTaken = cursor.getLong(INDEX_DATE_MODIFIED) * 1000;
64 | }
65 | long miniThumbMagic = cursor.getLong(INDEX_MIMI_THUMB_MAGIC);
66 | String title = cursor.getString(INDEX_TITLE);
67 | String mimeType = cursor.getString(INDEX_MIME_TYPE);
68 | if (title == null || title.length() == 0) {
69 | title = dataPath;
70 | }
71 | return new VideoObject(this, mContentResolver,
72 | id, cursor.getPosition(), contentUri(id), dataPath,
73 | mimeType, dateTaken, title);
74 | }
75 |
76 | public VideoList(ContentResolver resolver, Uri uri, int sort,
77 | String bucketId) {
78 | super(resolver, uri, sort, bucketId);
79 | }
80 |
81 | public HashMap getBucketIds() {
82 | Uri uri = mBaseUri.buildUpon()
83 | .appendQueryParameter("distinct", "true").build();
84 | Cursor c = Images.Media.query(
85 | mContentResolver, uri,
86 | new String[] {
87 | Media.BUCKET_DISPLAY_NAME,
88 | Media.BUCKET_ID
89 | },
90 | whereClause(), whereClauseArgs(), sortOrder());
91 | try {
92 | HashMap hash = new HashMap();
93 | while (c.moveToNext()) {
94 | hash.put(c.getString(1), c.getString(0));
95 | }
96 | return hash;
97 | } finally {
98 | c.close();
99 | }
100 | }
101 |
102 | protected String whereClause() {
103 | return mBucketId != null
104 | ? Images.Media.BUCKET_ID + " = '" + mBucketId + "'"
105 | : null;
106 | }
107 |
108 | protected String[] whereClauseArgs() {
109 | return null;
110 | }
111 |
112 | @Override
113 | protected Cursor createCursor() {
114 | Cursor c = Images.Media.query(
115 | mContentResolver, mBaseUri, VIDEO_PROJECTION,
116 | whereClause(), whereClauseArgs(), sortOrder());
117 | return c;
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/res/xml/gallery_preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
20 |
21 |
23 |
24 |
25 |
33 |
34 |
35 |
43 |
44 |
45 |
50 |
51 |
52 |
54 |
55 |
56 |
64 |
65 |
66 |
74 |
75 |
76 |
81 |
82 |
83 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/tests/src/com/android/camera/BitmapManagerUnitTests.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.gallery.IImage;
20 | import com.android.camera.gallery.IImageList;
21 |
22 | import android.content.Context;
23 | import android.graphics.Bitmap;
24 | import android.test.AndroidTestCase;
25 |
26 | /**
27 | * BitmapManager's unit tests.
28 | */
29 | public class BitmapManagerUnitTests extends AndroidTestCase {
30 | IImageList mImageList;
31 | IImage mImage;
32 | BitmapManager mBitmapManager;
33 | Context mContext;
34 |
35 | private class DecodeThread extends Thread {
36 | Bitmap bitmap;
37 |
38 | public DecodeThread() {
39 | }
40 |
41 | @Override
42 | public void run() {
43 | bitmap = mImage.thumbBitmap(IImage.ROTATE_AS_NEEDED);
44 | }
45 |
46 | public Bitmap getBitmap() {
47 | return bitmap;
48 | }
49 | }
50 |
51 | @Override
52 | public void setUp() {
53 | mContext = getContext();
54 | mBitmapManager = BitmapManager.instance();
55 | mImageList = ImageManager.makeImageList(
56 | mContext.getContentResolver(),
57 | ImageManager.DataLocation.ALL,
58 | ImageManager.INCLUDE_IMAGES,
59 | ImageManager.SORT_DESCENDING,
60 | null);
61 | mImage = mImageList.getImageAt(0);
62 | }
63 |
64 | public void testSingleton() {
65 | BitmapManager manager = BitmapManager.instance();
66 | assertNotNull(manager);
67 | assertNotNull(mBitmapManager);
68 | assertSame(manager, mBitmapManager);
69 | }
70 |
71 | public void testCanThreadDecoding() {
72 | Thread t = new DecodeThread();
73 |
74 | // By default all threads can decode.
75 | assertTrue(mBitmapManager.canThreadDecoding(t));
76 |
77 | // Disallow thread t to decode.
78 | mBitmapManager.cancelThreadDecoding(t, mContext.getContentResolver());
79 | assertFalse(mBitmapManager.canThreadDecoding(t));
80 |
81 | // Allow thread t to decode again.
82 | mBitmapManager.allowThreadDecoding(t);
83 | assertTrue(mBitmapManager.canThreadDecoding(t));
84 | }
85 |
86 | public void testDefaultAllowDecoding() {
87 | DecodeThread t = new DecodeThread();
88 | try {
89 | t.start();
90 | t.join();
91 | } catch (InterruptedException ex) {
92 | } finally {
93 | assertNotNull(t.getBitmap());
94 | }
95 | }
96 |
97 | public void testCancelDecoding() {
98 | DecodeThread t = new DecodeThread();
99 | mBitmapManager.cancelThreadDecoding(t, mContext.getContentResolver());
100 | try {
101 | t.start();
102 | t.join();
103 | } catch (InterruptedException ex) {
104 | } finally {
105 | assertNull(t.getBitmap());
106 | }
107 | }
108 |
109 | public void testAllowDecoding() {
110 | DecodeThread t = new DecodeThread();
111 | mBitmapManager.cancelThreadDecoding(t, mContext.getContentResolver());
112 | mBitmapManager.allowThreadDecoding(t);
113 | try {
114 | t.start();
115 | t.join();
116 | } catch (InterruptedException ex) {
117 | } finally {
118 | assertNotNull(t.getBitmap());
119 | }
120 | }
121 |
122 | public void testThreadDecoding() {
123 | DecodeThread t1 = new DecodeThread();
124 | DecodeThread t2 = new DecodeThread();
125 | mBitmapManager.allowThreadDecoding(t1);
126 | mBitmapManager.cancelThreadDecoding(t2, mContext.getContentResolver());
127 | t1.start();
128 | t2.start();
129 |
130 | try {
131 | t1.join();
132 | t2.join();
133 | } catch (InterruptedException ex) {
134 | } finally {
135 | assertTrue(mBitmapManager.canThreadDecoding(t1));
136 | assertNotNull(t1.getBitmap());
137 | assertFalse(mBitmapManager.canThreadDecoding(t2));
138 | assertNull(t2.getBitmap());
139 | }
140 | }
141 |
142 | @Override
143 | public String toString() {
144 | return "BitmapManagerUnitTest";
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/com/android/camera/EvenlySpacedLayout.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.gallery.R;
20 |
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.util.AttributeSet;
24 | import android.view.View;
25 | import android.view.ViewGroup;
26 |
27 | //
28 | // This is a layout which makes the children even spaced.
29 | // Currently it does not consider the padding parameters.
30 | //
31 | public class EvenlySpacedLayout extends ViewGroup {
32 | private boolean mHorizontal;
33 |
34 | // Wheather we keep the space in both ends of the layout
35 | private boolean mKeepEndSpace;
36 |
37 | public EvenlySpacedLayout(Context context, AttributeSet attrs) {
38 | super(context, attrs);
39 | TypedArray a = context.obtainStyledAttributes(
40 | attrs, R.styleable.EvenlySpacedLayout, 0, 0);
41 | mHorizontal = (0 == a.getInt(
42 | R.styleable.EvenlySpacedLayout_orientation, 0));
43 | mKeepEndSpace = a.getBoolean(
44 | R.styleable.EvenlySpacedLayout_keepEndSpace, true);
45 | a.recycle();
46 | }
47 |
48 | @Override
49 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
50 | int count = getChildCount();
51 | int width = 0;
52 | int height = 0;
53 | for (int i = 0; i < count; i++) {
54 | View child = getChildAt(i);
55 | if (child.getVisibility() == GONE) continue;
56 | measureChild(child, widthMeasureSpec, heightMeasureSpec);
57 | if (mHorizontal) {
58 | width += child.getMeasuredWidth();
59 | height = Math.max(height, child.getMeasuredHeight());
60 | } else {
61 | height += child.getMeasuredHeight();
62 | width = Math.max(width, child.getMeasuredWidth());
63 | }
64 | }
65 | setMeasuredDimension(resolveSize(width, widthMeasureSpec),
66 | resolveSize(height, heightMeasureSpec));
67 | }
68 |
69 | private void layoutHorizontal(boolean changed, int l, int t, int r, int b) {
70 | int count = getChildCount();
71 |
72 | int usedWidth = 0;
73 | int usedChildren = 0;
74 | for (int i = 0; i < count; i++) {
75 | View child = getChildAt(i);
76 | if (child.getVisibility() == GONE) continue;
77 | usedWidth += child.getMeasuredWidth();
78 | ++usedChildren;
79 | }
80 |
81 | int spacing = (r - l - usedWidth) /
82 | (mKeepEndSpace ? (usedChildren + 1) : (usedChildren - 1));
83 | int left = mKeepEndSpace ? spacing : 0;
84 | int top = 0;
85 | for (int i = 0; i < count; i++) {
86 | View child = getChildAt(i);
87 | if (child.getVisibility() == GONE) continue;
88 | int w = child.getMeasuredWidth();
89 | int h = child.getMeasuredHeight();
90 | child.layout(left, top, left + w, top + h);
91 | left += w;
92 | left += spacing;
93 | }
94 | }
95 |
96 | private void layoutVertical(boolean changed, int l, int t, int r, int b) {
97 | int count = getChildCount();
98 |
99 | int usedHeight = 0;
100 | int usedChildren = 0;
101 | for (int i = 0; i < count; i++) {
102 | View child = getChildAt(i);
103 | if (child.getVisibility() == GONE) continue;
104 | usedHeight += child.getMeasuredHeight();
105 | ++usedChildren;
106 | }
107 |
108 | int spacing = (b - t - usedHeight) /
109 | (mKeepEndSpace ? (usedChildren + 1) : (usedChildren - 1));
110 | int top = mKeepEndSpace ? spacing : 0;
111 | int left = 0;
112 | for (int i = 0; i < count; i++) {
113 | View child = getChildAt(i);
114 | if (child.getVisibility() == GONE) continue;
115 | int w = child.getMeasuredWidth();
116 | int h = child.getMeasuredHeight();
117 | child.layout(left, top, left + w, top + h);
118 | top += h;
119 | top += spacing;
120 | }
121 | }
122 |
123 | @Override
124 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
125 | if (mHorizontal) {
126 | layoutHorizontal(changed, l, t, r, b);
127 | } else {
128 | layoutVertical(changed, l, t, r, b);
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/res/layout/viewimage.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
21 |
22 |
25 |
30 |
35 |
36 |
37 |
40 |
45 |
46 |
56 |
57 |
67 |
68 |
74 |
81 |
88 |
95 |
102 |
109 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/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 | import java.util.HashMap;
25 |
26 | /**
27 | * Represents an ordered collection of Image objects. Provides an API to add
28 | * and remove an image.
29 | */
30 | public class ImageList extends BaseImageList implements IImageList {
31 |
32 | @SuppressWarnings("unused")
33 | private static final String TAG = "ImageList";
34 |
35 | private static final String[] ACCEPTABLE_IMAGE_TYPES =
36 | new String[] { "image/jpeg", "image/png", "image/gif" };
37 |
38 | public HashMap getBucketIds() {
39 | Uri uri = mBaseUri.buildUpon()
40 | .appendQueryParameter("distinct", "true").build();
41 | Cursor cursor = Media.query(
42 | mContentResolver, uri,
43 | new String[] {
44 | Media.BUCKET_DISPLAY_NAME,
45 | Media.BUCKET_ID},
46 | whereClause(), whereClauseArgs(), null);
47 | try {
48 | HashMap hash = new HashMap();
49 | while (cursor.moveToNext()) {
50 | hash.put(cursor.getString(1), cursor.getString(0));
51 | }
52 | return hash;
53 | } finally {
54 | cursor.close();
55 | }
56 | }
57 |
58 | /**
59 | * ImageList constructor.
60 | */
61 | public ImageList(ContentResolver resolver, Uri imageUri,
62 | int sort, String bucketId) {
63 | super(resolver, imageUri, sort, bucketId);
64 | }
65 |
66 | private static final String WHERE_CLAUSE =
67 | "(" + Media.MIME_TYPE + " in (?, ?, ?))";
68 | private static final String WHERE_CLAUSE_WITH_BUCKET_ID =
69 | WHERE_CLAUSE + " AND " + Media.BUCKET_ID + " = ?";
70 |
71 | protected String whereClause() {
72 | return mBucketId == null ? WHERE_CLAUSE : WHERE_CLAUSE_WITH_BUCKET_ID;
73 | }
74 |
75 | protected String[] whereClauseArgs() {
76 | // TODO: Since mBucketId won't change, we should keep the array.
77 | if (mBucketId != null) {
78 | int count = ACCEPTABLE_IMAGE_TYPES.length;
79 | String[] result = new String[count + 1];
80 | System.arraycopy(ACCEPTABLE_IMAGE_TYPES, 0, result, 0, count);
81 | result[count] = mBucketId;
82 | return result;
83 | }
84 | return ACCEPTABLE_IMAGE_TYPES;
85 | }
86 |
87 | @Override
88 | protected Cursor createCursor() {
89 | Cursor c = Media.query(
90 | mContentResolver, mBaseUri, IMAGE_PROJECTION,
91 | whereClause(), whereClauseArgs(), sortOrder());
92 | return c;
93 | }
94 |
95 | static final String[] IMAGE_PROJECTION = new String[] {
96 | Media._ID,
97 | Media.DATA,
98 | Media.DATE_TAKEN,
99 | Media.MINI_THUMB_MAGIC,
100 | Media.ORIENTATION,
101 | Media.TITLE,
102 | Media.MIME_TYPE,
103 | Media.DATE_MODIFIED};
104 |
105 | private static final int INDEX_ID = 0;
106 | private static final int INDEX_DATA_PATH = 1;
107 | private static final int INDEX_DATE_TAKEN = 2;
108 | private static final int INDEX_MINI_THUMB_MAGIC = 3;
109 | private static final int INDEX_ORIENTATION = 4;
110 | private static final int INDEX_TITLE = 5;
111 | private static final int INDEX_MIME_TYPE = 6;
112 | private static final int INDEX_DATE_MODIFIED = 7;
113 |
114 | @Override
115 | protected long getImageId(Cursor cursor) {
116 | return cursor.getLong(INDEX_ID);
117 | }
118 |
119 | @Override
120 | protected BaseImage loadImageFromCursor(Cursor cursor) {
121 | long id = cursor.getLong(INDEX_ID);
122 | String dataPath = cursor.getString(INDEX_DATA_PATH);
123 | long dateTaken = cursor.getLong(INDEX_DATE_TAKEN);
124 | if (dateTaken == 0) {
125 | dateTaken = cursor.getLong(INDEX_DATE_MODIFIED) * 1000;
126 | }
127 | long miniThumbMagic = cursor.getLong(INDEX_MINI_THUMB_MAGIC);
128 | int orientation = cursor.getInt(INDEX_ORIENTATION);
129 | String title = cursor.getString(INDEX_TITLE);
130 | String mimeType = cursor.getString(INDEX_MIME_TYPE);
131 | if (title == null || title.length() == 0) {
132 | title = dataPath;
133 | }
134 | return new Image(this, mContentResolver, id, cursor.getPosition(),
135 | contentUri(id), dataPath, mimeType, dateTaken, title,
136 | orientation);
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/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 com.android.camera.BitmapManager;
20 | import com.android.camera.Util;
21 |
22 | import android.content.ContentResolver;
23 | import android.content.ContentValues;
24 | import android.graphics.Bitmap;
25 | import android.graphics.BitmapFactory;
26 | import android.media.ExifInterface;
27 | import android.net.Uri;
28 | import android.provider.BaseColumns;
29 | import android.provider.MediaStore.Images;
30 | import android.provider.MediaStore.Images.ImageColumns;
31 | import android.util.Log;
32 |
33 | import java.io.IOException;
34 |
35 | /**
36 | * The class for normal images in gallery.
37 | */
38 | public class Image extends BaseImage implements IImage {
39 | private static final String TAG = "BaseImage";
40 |
41 | private ExifInterface mExif;
42 |
43 | private int mRotation;
44 |
45 | public Image(BaseImageList container, ContentResolver cr,
46 | long id, int index, Uri uri, String dataPath,
47 | String mimeType, long dateTaken, String title,
48 | int rotation) {
49 | super(container, cr, id, index, uri, dataPath,
50 | mimeType, dateTaken, title);
51 | mRotation = rotation;
52 | }
53 |
54 | @Override
55 | public int getDegreesRotated() {
56 | return mRotation;
57 | }
58 |
59 | protected void setDegreesRotated(int degrees) {
60 | if (mRotation == degrees) return;
61 | mRotation = degrees;
62 | ContentValues values = new ContentValues();
63 | values.put(ImageColumns.ORIENTATION, mRotation);
64 | mContentResolver.update(mUri, values, null, null);
65 |
66 | //TODO: Consider invalidate the cursor in container
67 | // ((BaseImageList) getContainer()).invalidateCursor();
68 | }
69 |
70 | public boolean isReadonly() {
71 | String mimeType = getMimeType();
72 | return !"image/jpeg".equals(mimeType) && !"image/png".equals(mimeType);
73 | }
74 |
75 | public boolean isDrm() {
76 | return false;
77 | }
78 |
79 | /**
80 | * Replaces the tag if already there. Otherwise, adds to the exif tags.
81 | * @param tag
82 | * @param value
83 | */
84 | public void replaceExifTag(String tag, String value) {
85 | if (mExif == null) {
86 | loadExifData();
87 | }
88 | mExif.setAttribute(tag, value);
89 | }
90 |
91 | private void loadExifData() {
92 | try {
93 | mExif = new ExifInterface(mDataPath);
94 | } catch (IOException ex) {
95 | Log.e(TAG, "cannot read exif", ex);
96 | }
97 | }
98 |
99 | private void saveExifData() throws IOException {
100 | if (mExif != null) {
101 | mExif.saveAttributes();
102 | }
103 | }
104 |
105 | private void setExifRotation(int degrees) {
106 | try {
107 | degrees %= 360;
108 | if (degrees < 0) degrees += 360;
109 |
110 | int orientation = ExifInterface.ORIENTATION_NORMAL;
111 | switch (degrees) {
112 | case 0:
113 | orientation = ExifInterface.ORIENTATION_NORMAL;
114 | break;
115 | case 90:
116 | orientation = ExifInterface.ORIENTATION_ROTATE_90;
117 | break;
118 | case 180:
119 | orientation = ExifInterface.ORIENTATION_ROTATE_180;
120 | break;
121 | case 270:
122 | orientation = ExifInterface.ORIENTATION_ROTATE_270;
123 | break;
124 | }
125 |
126 | replaceExifTag(ExifInterface.TAG_ORIENTATION,
127 | Integer.toString(orientation));
128 | saveExifData();
129 | } catch (Exception ex) {
130 | Log.e(TAG, "unable to save exif data with new orientation "
131 | + fullSizeImageUri(), ex);
132 | }
133 | }
134 |
135 | /**
136 | * Save the rotated image by updating the Exif "Orientation" tag.
137 | * @param degrees
138 | */
139 | public boolean rotateImageBy(int degrees) {
140 | int newDegrees = (getDegreesRotated() + degrees) % 360;
141 | setExifRotation(newDegrees);
142 | setDegreesRotated(newDegrees);
143 |
144 | return true;
145 | }
146 |
147 | private static final String[] THUMB_PROJECTION = new String[] {
148 | BaseColumns._ID,
149 | };
150 |
151 | public Bitmap thumbBitmap(boolean rotateAsNeeded) {
152 | Bitmap bitmap = null;
153 | BitmapFactory.Options options = new BitmapFactory.Options();
154 | options.inDither = false;
155 | options.inPreferredConfig = Bitmap.Config.ARGB_8888;
156 | bitmap = BitmapManager.instance().getThumbnail(mContentResolver, mId,
157 | Images.Thumbnails.MINI_KIND, options, false);
158 |
159 | if (bitmap != null && rotateAsNeeded) {
160 | bitmap = Util.rotate(bitmap, getDegreesRotated());
161 | }
162 |
163 | return bitmap;
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/src/com/android/camera/ImageLoader.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 com.android.camera.gallery.IImage;
20 |
21 | import android.content.ContentResolver;
22 | import android.graphics.Bitmap;
23 | import android.os.Handler;
24 | import android.provider.MediaStore;
25 | import android.util.Log;
26 |
27 | import java.util.ArrayList;
28 |
29 | /**
30 | * A dedicated decoding thread used by ImageGallery.
31 | */
32 | public class ImageLoader {
33 | @SuppressWarnings("unused")
34 | private static final String TAG = "ImageLoader";
35 |
36 | // Queue of work to do in the worker thread. The work is done in order.
37 | private final ArrayList mQueue = new ArrayList();
38 |
39 | // the worker thread and a done flag so we know when to exit
40 | private boolean mDone;
41 | private Thread mDecodeThread;
42 | private ContentResolver mCr;
43 |
44 | public interface LoadedCallback {
45 | public void run(Bitmap result);
46 | }
47 |
48 | public void getBitmap(IImage image,
49 | LoadedCallback imageLoadedRunnable,
50 | int tag) {
51 | if (mDecodeThread == null) {
52 | start();
53 | }
54 | synchronized (mQueue) {
55 | WorkItem w = new WorkItem(image, imageLoadedRunnable, tag);
56 | mQueue.add(w);
57 | mQueue.notifyAll();
58 | }
59 | }
60 |
61 | public boolean cancel(final IImage image) {
62 | synchronized (mQueue) {
63 | int index = findItem(image);
64 | if (index >= 0) {
65 | mQueue.remove(index);
66 | return true;
67 | } else {
68 | return false;
69 | }
70 | }
71 | }
72 |
73 | // The caller should hold mQueue lock.
74 | private int findItem(IImage image) {
75 | for (int i = 0; i < mQueue.size(); i++) {
76 | if (mQueue.get(i).mImage == image) {
77 | return i;
78 | }
79 | }
80 | return -1;
81 | }
82 |
83 | // Clear the queue. Returns an array of tags that were in the queue.
84 | public int[] clearQueue() {
85 | synchronized (mQueue) {
86 | int n = mQueue.size();
87 | int[] tags = new int[n];
88 | for (int i = 0; i < n; i++) {
89 | tags[i] = mQueue.get(i).mTag;
90 | }
91 | mQueue.clear();
92 | return tags;
93 | }
94 | }
95 |
96 | private static class WorkItem {
97 | IImage mImage;
98 | LoadedCallback mOnLoadedRunnable;
99 | int mTag;
100 |
101 | WorkItem(IImage image, LoadedCallback onLoadedRunnable, int tag) {
102 | mImage = image;
103 | mOnLoadedRunnable = onLoadedRunnable;
104 | mTag = tag;
105 | }
106 | }
107 |
108 | public ImageLoader(ContentResolver cr, Handler handler) {
109 | mCr = cr;
110 | start();
111 | }
112 |
113 | private class WorkerThread implements Runnable {
114 |
115 | // Pick off items on the queue, one by one, and compute their bitmap.
116 | // Place the resulting bitmap in the cache, then call back by executing
117 | // the given runnable so things can get updated appropriately.
118 | public void run() {
119 | while (true) {
120 | WorkItem workItem = null;
121 | synchronized (mQueue) {
122 | if (mDone) {
123 | break;
124 | }
125 | if (!mQueue.isEmpty()) {
126 | workItem = mQueue.remove(0);
127 | } else {
128 | try {
129 | mQueue.wait();
130 | } catch (InterruptedException ex) {
131 | // ignore the exception
132 | }
133 | continue;
134 | }
135 | }
136 |
137 | final Bitmap b = workItem.mImage.miniThumbBitmap();
138 |
139 | if (workItem.mOnLoadedRunnable != null) {
140 | workItem.mOnLoadedRunnable.run(b);
141 | }
142 | }
143 | }
144 | }
145 |
146 | private void start() {
147 | if (mDecodeThread != null) {
148 | return;
149 | }
150 |
151 | mDone = false;
152 | Thread t = new Thread(new WorkerThread());
153 | t.setName("image-loader");
154 | mDecodeThread = t;
155 | t.start();
156 | }
157 |
158 | public void stop() {
159 | synchronized (mQueue) {
160 | mDone = true;
161 | mQueue.notifyAll();
162 | }
163 | if (mDecodeThread != null) {
164 | try {
165 | Thread t = mDecodeThread;
166 | BitmapManager.instance().cancelThreadDecoding(t, mCr);
167 | t.join();
168 | mDecodeThread = null;
169 | } catch (InterruptedException ex) {
170 | // so now what?
171 | }
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/src/com/android/camera/gallery/UriImage.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.graphics.BitmapFactory;
25 | import android.net.Uri;
26 | import android.os.ParcelFileDescriptor;
27 | import android.util.Log;
28 |
29 | import java.io.File;
30 | import java.io.FileNotFoundException;
31 | import java.io.InputStream;
32 |
33 | class UriImage implements IImage {
34 | private static final String TAG = "UriImage";
35 | private final Uri mUri;
36 | private final IImageList mContainer;
37 | private final ContentResolver mContentResolver;
38 |
39 | UriImage(IImageList container, ContentResolver cr, Uri uri) {
40 | mContainer = container;
41 | mContentResolver = cr;
42 | mUri = uri;
43 | }
44 |
45 | public int getDegreesRotated() {
46 | return 0;
47 | }
48 |
49 | public String getDataPath() {
50 | return mUri.getPath();
51 | }
52 |
53 | private InputStream getInputStream() {
54 | try {
55 | if (mUri.getScheme().equals("file")) {
56 | return new java.io.FileInputStream(mUri.getPath());
57 | } else {
58 | return mContentResolver.openInputStream(mUri);
59 | }
60 | } catch (FileNotFoundException ex) {
61 | return null;
62 | }
63 | }
64 |
65 | private ParcelFileDescriptor getPFD() {
66 | try {
67 | if (mUri.getScheme().equals("file")) {
68 | String path = mUri.getPath();
69 | return ParcelFileDescriptor.open(new File(path),
70 | ParcelFileDescriptor.MODE_READ_ONLY);
71 | } else {
72 | return mContentResolver.openFileDescriptor(mUri, "r");
73 | }
74 | } catch (FileNotFoundException ex) {
75 | return null;
76 | }
77 | }
78 |
79 | public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels) {
80 | return fullSizeBitmap(minSideLength, maxNumberOfPixels,
81 | IImage.ROTATE_AS_NEEDED, IImage.NO_NATIVE);
82 | }
83 |
84 | public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels,
85 | boolean rotateAsNeeded) {
86 | return fullSizeBitmap(minSideLength, maxNumberOfPixels,
87 | rotateAsNeeded, IImage.NO_NATIVE);
88 | }
89 |
90 | public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels,
91 | boolean rotateAsNeeded, boolean useNative) {
92 | try {
93 | ParcelFileDescriptor pfdInput = getPFD();
94 | Bitmap b = Util.makeBitmap(minSideLength, maxNumberOfPixels,
95 | pfdInput, useNative);
96 | return b;
97 | } catch (Exception ex) {
98 | Log.e(TAG, "got exception decoding bitmap ", ex);
99 | return null;
100 | }
101 | }
102 |
103 | public Uri fullSizeImageUri() {
104 | return mUri;
105 | }
106 |
107 | public InputStream fullSizeImageData() {
108 | return getInputStream();
109 | }
110 |
111 | public Bitmap miniThumbBitmap() {
112 | return thumbBitmap(IImage.ROTATE_AS_NEEDED);
113 | }
114 |
115 | public String getTitle() {
116 | return mUri.toString();
117 | }
118 |
119 | public Bitmap thumbBitmap(boolean rotateAsNeeded) {
120 | return fullSizeBitmap(THUMBNAIL_TARGET_SIZE, THUMBNAIL_MAX_NUM_PIXELS,
121 | rotateAsNeeded);
122 | }
123 |
124 | private BitmapFactory.Options snifBitmapOptions() {
125 | ParcelFileDescriptor input = getPFD();
126 | if (input == null) return null;
127 | try {
128 | BitmapFactory.Options options = new BitmapFactory.Options();
129 | options.inJustDecodeBounds = true;
130 | BitmapManager.instance().decodeFileDescriptor(
131 | input.getFileDescriptor(), options);
132 | return options;
133 | } finally {
134 | Util.closeSilently(input);
135 | }
136 | }
137 |
138 | public String getMimeType() {
139 | BitmapFactory.Options options = snifBitmapOptions();
140 | return (options != null && options.outMimeType != null)
141 | ? options.outMimeType
142 | : "";
143 | }
144 |
145 | public int getHeight() {
146 | BitmapFactory.Options options = snifBitmapOptions();
147 | return (options != null) ? options.outHeight : 0;
148 | }
149 |
150 | public int getWidth() {
151 | BitmapFactory.Options options = snifBitmapOptions();
152 | return (options != null) ? options.outWidth : 0;
153 | }
154 |
155 | public IImageList getContainer() {
156 | return mContainer;
157 | }
158 |
159 | public long getDateTaken() {
160 | return 0;
161 | }
162 |
163 | public boolean isReadonly() {
164 | return true;
165 | }
166 |
167 | public boolean isDrm() {
168 | return false;
169 | }
170 |
171 | public boolean rotateImageBy(int degrees) {
172 | return false;
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/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.graphics.BitmapFactory;
25 | import android.net.Uri;
26 | import android.os.ParcelFileDescriptor;
27 | import android.provider.MediaStore.Images;
28 | import android.util.Log;
29 |
30 | import java.io.FileNotFoundException;
31 | import java.io.IOException;
32 | import java.io.InputStream;
33 |
34 | /**
35 | * Represents a particular image and provides access to the underlying bitmap
36 | * and two thumbnail bitmaps as well as other information such as the id, and
37 | * the path to the actual image data.
38 | */
39 | public abstract class BaseImage implements IImage {
40 | private static final String TAG = "BaseImage";
41 | private static final int UNKNOWN_LENGTH = -1;
42 | protected ContentResolver mContentResolver;
43 |
44 | // Database field
45 | protected Uri mUri;
46 | protected long mId;
47 | protected String mDataPath;
48 | protected final int mIndex;
49 | protected String mMimeType;
50 | private final long mDateTaken;
51 | private String mTitle;
52 |
53 | protected BaseImageList mContainer;
54 |
55 | private int mWidth = UNKNOWN_LENGTH;
56 | private int mHeight = UNKNOWN_LENGTH;
57 |
58 | protected BaseImage(BaseImageList container, ContentResolver cr,
59 | long id, int index, Uri uri, String dataPath, String mimeType,
60 | long dateTaken, String title) {
61 | mContainer = container;
62 | mContentResolver = cr;
63 | mId = id;
64 | mIndex = index;
65 | mUri = uri;
66 | mDataPath = dataPath;
67 | mMimeType = mimeType;
68 | mDateTaken = dateTaken;
69 | mTitle = title;
70 | }
71 |
72 | public String getDataPath() {
73 | return mDataPath;
74 | }
75 |
76 | @Override
77 | public boolean equals(Object other) {
78 | if (other == null || !(other instanceof Image)) return false;
79 | return mUri.equals(((Image) other).mUri);
80 | }
81 |
82 | @Override
83 | public int hashCode() {
84 | return mUri.hashCode();
85 | }
86 |
87 | public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels) {
88 | return fullSizeBitmap(minSideLength, maxNumberOfPixels,
89 | IImage.ROTATE_AS_NEEDED, IImage.NO_NATIVE);
90 | }
91 |
92 | public Bitmap fullSizeBitmap(int minSideLength, int maxNumberOfPixels,
93 | boolean rotateAsNeeded, boolean useNative) {
94 | Uri url = mContainer.contentUri(mId);
95 | if (url == null) return null;
96 |
97 | Bitmap b = Util.makeBitmap(minSideLength, maxNumberOfPixels,
98 | url, mContentResolver, useNative);
99 |
100 | if (b != null && rotateAsNeeded) {
101 | b = Util.rotate(b, getDegreesRotated());
102 | }
103 |
104 | return b;
105 | }
106 |
107 | public InputStream fullSizeImageData() {
108 | try {
109 | InputStream input = mContentResolver.openInputStream(mUri);
110 | return input;
111 | } catch (IOException ex) {
112 | return null;
113 | }
114 | }
115 |
116 | public Uri fullSizeImageUri() {
117 | return mUri;
118 | }
119 |
120 | public IImageList getContainer() {
121 | return mContainer;
122 | }
123 |
124 | public long getDateTaken() {
125 | return mDateTaken;
126 | }
127 |
128 | public int getDegreesRotated() {
129 | return 0;
130 | }
131 |
132 | public String getMimeType() {
133 | return mMimeType;
134 | }
135 |
136 | public String getTitle() {
137 | return mTitle;
138 | }
139 |
140 | private void setupDimension() {
141 | ParcelFileDescriptor input = null;
142 | try {
143 | input = mContentResolver.openFileDescriptor(mUri, "r");
144 | BitmapFactory.Options options = new BitmapFactory.Options();
145 | options.inJustDecodeBounds = true;
146 | BitmapManager.instance().decodeFileDescriptor(
147 | input.getFileDescriptor(), options);
148 | mWidth = options.outWidth;
149 | mHeight = options.outHeight;
150 | } catch (FileNotFoundException ex) {
151 | mWidth = 0;
152 | mHeight = 0;
153 | } finally {
154 | Util.closeSilently(input);
155 | }
156 | }
157 |
158 | public int getWidth() {
159 | if (mWidth == UNKNOWN_LENGTH) setupDimension();
160 | return mWidth;
161 | }
162 |
163 | public int getHeight() {
164 | if (mHeight == UNKNOWN_LENGTH) setupDimension();
165 | return mHeight;
166 | }
167 |
168 | public Bitmap miniThumbBitmap() {
169 | Bitmap b = null;
170 | try {
171 | long id = mId;
172 | b = BitmapManager.instance().getThumbnail(mContentResolver, id,
173 | Images.Thumbnails.MICRO_KIND, null, false);
174 | } catch (Throwable ex) {
175 | Log.e(TAG, "miniThumbBitmap got exception", ex);
176 | return null;
177 | }
178 | if (b != null) {
179 | b = Util.rotate(b, getDegreesRotated());
180 | }
181 | return b;
182 | }
183 |
184 | protected void onRemove() {
185 | }
186 |
187 | @Override
188 | public String toString() {
189 | return mUri.toString();
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/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 | * This class provides several utilities to cancel bitmap decoding.
31 | *
32 | * The function decodeFileDescriptor() is used to decode a bitmap. During
33 | * decoding if another thread wants to cancel it, it calls the function
34 | * cancelThreadDecoding() specifying the Thread which is in decoding.
35 | *
36 | * cancelThreadDecoding() is sticky until allowThreadDecoding() is called.
37 | */
38 | public class BitmapManager {
39 | private static final String TAG = "BitmapManager";
40 | private static enum State {CANCEL, ALLOW}
41 | private static class ThreadStatus {
42 | public State mState = State.ALLOW;
43 | public BitmapFactory.Options mOptions;
44 | public boolean mThumbRequesting;
45 | @Override
46 | public String toString() {
47 | String s;
48 | if (mState == State.CANCEL) {
49 | s = "Cancel";
50 | } else if (mState == State.ALLOW) {
51 | s = "Allow";
52 | } else {
53 | s = "?";
54 | }
55 | s = "thread state = " + s + ", options = " + mOptions;
56 | return s;
57 | }
58 | }
59 |
60 | private final WeakHashMap mThreadStatus =
61 | new WeakHashMap();
62 |
63 | private static BitmapManager sManager = null;
64 |
65 | private BitmapManager() {
66 | }
67 |
68 | /**
69 | * Get thread status and create one if specified.
70 | */
71 | private synchronized ThreadStatus getOrCreateThreadStatus(Thread t) {
72 | ThreadStatus status = mThreadStatus.get(t);
73 | if (status == null) {
74 | status = new ThreadStatus();
75 | mThreadStatus.put(t, status);
76 | }
77 | return status;
78 | }
79 |
80 | /**
81 | * The following three methods are used to keep track of
82 | * BitmapFaction.Options used for decoding and cancelling.
83 | */
84 | private synchronized void setDecodingOptions(Thread t,
85 | BitmapFactory.Options options) {
86 | getOrCreateThreadStatus(t).mOptions = options;
87 | }
88 |
89 | synchronized void removeDecodingOptions(Thread t) {
90 | ThreadStatus status = mThreadStatus.get(t);
91 | status.mOptions = null;
92 | }
93 |
94 | /**
95 | * The following three methods are used to keep track of which thread
96 | * is being disabled for bitmap decoding.
97 | */
98 | public synchronized boolean canThreadDecoding(Thread t) {
99 | ThreadStatus status = mThreadStatus.get(t);
100 | if (status == null) {
101 | // allow decoding by default
102 | return true;
103 | }
104 |
105 | boolean result = (status.mState != State.CANCEL);
106 | return result;
107 | }
108 |
109 | public synchronized void allowThreadDecoding(Thread t) {
110 | getOrCreateThreadStatus(t).mState = State.ALLOW;
111 | }
112 |
113 | public synchronized void cancelThreadDecoding(Thread t, ContentResolver cr) {
114 | ThreadStatus status = getOrCreateThreadStatus(t);
115 | status.mState = State.CANCEL;
116 | if (status.mOptions != null) {
117 | status.mOptions.requestCancelDecode();
118 | }
119 |
120 | // Wake up threads in waiting list
121 | notifyAll();
122 |
123 | // Since our cancel request can arrive MediaProvider earlier than getThumbnail request,
124 | // we use mThumbRequesting flag to make sure our request does cancel the request.
125 | try {
126 | synchronized (status) {
127 | while (status.mThumbRequesting) {
128 | Images.Thumbnails.cancelThumbnailRequest(cr, -1, t.getId());
129 | Video.Thumbnails.cancelThumbnailRequest(cr, -1, t.getId());
130 | status.wait(200);
131 | }
132 | }
133 | } catch (InterruptedException ex) {
134 | // ignore it.
135 | }
136 | }
137 |
138 | public Bitmap getThumbnail(ContentResolver cr, long origId, int kind,
139 | BitmapFactory.Options options, boolean isVideo) {
140 | Thread t = Thread.currentThread();
141 | ThreadStatus status = getOrCreateThreadStatus(t);
142 |
143 | if (!canThreadDecoding(t)) {
144 | Log.d(TAG, "Thread " + t + " is not allowed to decode.");
145 | return null;
146 | }
147 |
148 | try {
149 | synchronized (status) {
150 | status.mThumbRequesting = true;
151 | }
152 | if (isVideo) {
153 | return Video.Thumbnails.getThumbnail(cr, origId, t.getId(),
154 | kind, null);
155 | } else {
156 | return Images.Thumbnails.getThumbnail(cr, origId, t.getId(),
157 | kind, null);
158 | }
159 | } finally {
160 | synchronized (status) {
161 | status.mThumbRequesting = false;
162 | status.notifyAll();
163 | }
164 | }
165 | }
166 |
167 | public static synchronized BitmapManager instance() {
168 | if (sManager == null) {
169 | sManager = new BitmapManager();
170 | }
171 | return sManager;
172 | }
173 |
174 | /**
175 | * The real place to delegate bitmap decoding to BitmapFactory.
176 | */
177 | public Bitmap decodeFileDescriptor(FileDescriptor fd,
178 | BitmapFactory.Options options) {
179 | if (options.mCancel) {
180 | return null;
181 | }
182 |
183 | Thread thread = Thread.currentThread();
184 | if (!canThreadDecoding(thread)) {
185 | Log.d(TAG, "Thread " + thread + " is not allowed to decode.");
186 | return null;
187 | }
188 |
189 | setDecodingOptions(thread, options);
190 | Bitmap b = BitmapFactory.decodeFileDescriptor(fd, null, options);
191 |
192 | removeDecodingOptions(thread);
193 | return b;
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/src/com/android/camera/PhotoAppWidgetProvider.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.gallery.R;
20 |
21 | import android.appwidget.AppWidgetManager;
22 | import android.appwidget.AppWidgetProvider;
23 | import android.content.ContentValues;
24 | import android.content.Context;
25 | import android.database.Cursor;
26 | import android.database.sqlite.SQLiteDatabase;
27 | import android.database.sqlite.SQLiteException;
28 | import android.database.sqlite.SQLiteOpenHelper;
29 | import android.graphics.Bitmap;
30 | import android.graphics.BitmapFactory;
31 | import android.util.Log;
32 | import android.widget.RemoteViews;
33 |
34 | import java.io.ByteArrayOutputStream;
35 | import java.io.IOException;
36 |
37 | /**
38 | * Simple widget to show a user-selected picture.
39 | */
40 | public class PhotoAppWidgetProvider extends AppWidgetProvider {
41 | private static final String TAG = "PhotoAppWidgetProvider";
42 | private static final boolean LOGD = true;
43 |
44 | @Override
45 | public void onUpdate(Context context, AppWidgetManager appWidgetManager,
46 | int[] appWidgetIds) {
47 | // Update each requested appWidgetId with its unique photo
48 | PhotoDatabaseHelper helper = new PhotoDatabaseHelper(context);
49 | for (int appWidgetId : appWidgetIds) {
50 | int[] specificAppWidget = new int[] { appWidgetId };
51 | RemoteViews views = buildUpdate(context, appWidgetId, helper);
52 | if (LOGD) {
53 | Log.d(TAG, "sending out views=" + views
54 | + " for id=" + appWidgetId);
55 | }
56 | appWidgetManager.updateAppWidget(specificAppWidget, views);
57 | }
58 | helper.close();
59 | }
60 |
61 | @Override
62 | public void onDeleted(Context context, int[] appWidgetIds) {
63 | // Clean deleted photos out of our database
64 | PhotoDatabaseHelper helper = new PhotoDatabaseHelper(context);
65 | for (int appWidgetId : appWidgetIds) {
66 | helper.deletePhoto(appWidgetId);
67 | }
68 | helper.close();
69 | }
70 |
71 | /**
72 | * Load photo for given widget and build {@link RemoteViews} for it.
73 | */
74 | static RemoteViews buildUpdate(Context context, int appWidgetId,
75 | PhotoDatabaseHelper helper) {
76 | RemoteViews views = null;
77 | Bitmap bitmap = helper.getPhoto(appWidgetId);
78 | if (bitmap != null) {
79 | views = new RemoteViews(context.getPackageName(),
80 | R.layout.photo_frame);
81 | views.setImageViewBitmap(R.id.photo, bitmap);
82 | }
83 | return views;
84 | }
85 |
86 | static class PhotoDatabaseHelper extends SQLiteOpenHelper {
87 | private static final String DATABASE_NAME = "launcher.db";
88 |
89 | private static final int DATABASE_VERSION = 2;
90 |
91 | static final String TABLE_PHOTOS = "photos";
92 | static final String FIELD_APPWIDGET_ID = "appWidgetId";
93 | static final String FIELD_PHOTO_BLOB = "photoBlob";
94 |
95 | PhotoDatabaseHelper(Context context) {
96 | super(context, DATABASE_NAME, null, DATABASE_VERSION);
97 | }
98 |
99 | @Override
100 | public void onCreate(SQLiteDatabase db) {
101 | db.execSQL("CREATE TABLE " + TABLE_PHOTOS + " (" +
102 | FIELD_APPWIDGET_ID + " INTEGER PRIMARY KEY," +
103 | FIELD_PHOTO_BLOB + " BLOB" +
104 | ");");
105 | }
106 |
107 | @Override
108 | public void onUpgrade(SQLiteDatabase db, int oldVersion,
109 | int newVersion) {
110 | int version = oldVersion;
111 |
112 | if (version != DATABASE_VERSION) {
113 | Log.w(TAG, "Destroying all old data.");
114 | db.execSQL("DROP TABLE IF EXISTS " + TABLE_PHOTOS);
115 | onCreate(db);
116 | }
117 | }
118 |
119 | /**
120 | * Store the given bitmap in this database for the given appWidgetId.
121 | */
122 | public boolean setPhoto(int appWidgetId, Bitmap bitmap) {
123 | boolean success = false;
124 | try {
125 | // Try go guesstimate how much space the icon will take when
126 | // serialized to avoid unnecessary allocations/copies during
127 | // the write.
128 | int size = bitmap.getWidth() * bitmap.getHeight() * 4;
129 | ByteArrayOutputStream out = new ByteArrayOutputStream(size);
130 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
131 | out.flush();
132 | out.close();
133 |
134 | ContentValues values = new ContentValues();
135 | values.put(PhotoDatabaseHelper.FIELD_APPWIDGET_ID, appWidgetId);
136 | values.put(PhotoDatabaseHelper.FIELD_PHOTO_BLOB,
137 | out.toByteArray());
138 |
139 | SQLiteDatabase db = getWritableDatabase();
140 | db.insertOrThrow(PhotoDatabaseHelper.TABLE_PHOTOS, null,
141 | values);
142 |
143 | success = true;
144 | } catch (SQLiteException e) {
145 | Log.e(TAG, "Could not open database", e);
146 | } catch (IOException e) {
147 | Log.e(TAG, "Could not serialize photo", e);
148 | }
149 | if (LOGD) {
150 | Log.d(TAG, "setPhoto success=" + success);
151 | }
152 | return success;
153 | }
154 |
155 | static final String[] PHOTOS_PROJECTION = {
156 | FIELD_PHOTO_BLOB,
157 | };
158 |
159 | static final int INDEX_PHOTO_BLOB = 0;
160 |
161 | /**
162 | * Inflate and return a bitmap for the given appWidgetId.
163 | */
164 | public Bitmap getPhoto(int appWidgetId) {
165 | Cursor c = null;
166 | Bitmap bitmap = null;
167 | try {
168 | SQLiteDatabase db = getReadableDatabase();
169 | String selection = String.format("%s=%d", FIELD_APPWIDGET_ID,
170 | appWidgetId);
171 | c = db.query(TABLE_PHOTOS, PHOTOS_PROJECTION, selection, null,
172 | null, null, null, null);
173 |
174 | if (c != null && LOGD) {
175 | Log.d(TAG, "getPhoto query count=" + c.getCount());
176 | }
177 |
178 | if (c != null && c.moveToFirst()) {
179 | byte[] data = c.getBlob(INDEX_PHOTO_BLOB);
180 | if (data != null) {
181 | bitmap = BitmapFactory.decodeByteArray(data, 0,
182 | data.length);
183 | }
184 | }
185 | } catch (SQLiteException e) {
186 | Log.e(TAG, "Could not load photo from database", e);
187 | } finally {
188 | if (c != null) {
189 | c.close();
190 | }
191 | }
192 | return bitmap;
193 | }
194 |
195 | /**
196 | * Remove any bitmap associated with the given appWidgetId.
197 | */
198 | public void deletePhoto(int appWidgetId) {
199 | try {
200 | SQLiteDatabase db = getWritableDatabase();
201 | String whereClause = String.format("%s=%d", FIELD_APPWIDGET_ID,
202 | appWidgetId);
203 | db.delete(TABLE_PHOTOS, whereClause, null);
204 | } catch (SQLiteException e) {
205 | Log.e(TAG, "Could not delete photo from database", e);
206 | }
207 | }
208 | }
209 |
210 | }
211 |
212 |
--------------------------------------------------------------------------------