Use debug.Log instead of android.util.Log.

see http://ag/438423, merge conflicts solved.

1. Change to use com.android.camera.debug.Log instead of android.util.Log.
2. Add DebugCameraProxy to support more detailed debug info.
3. Add CameraErrorCallback in CameraManager.
4. Support posting to a specific handler for CameraErrorCallback.
5. Trim down some TAGs to match the framework tag length limit.
6. Remove some unused codes in CameraSettings.

bug:13324870

Change-Id: I8c20a8a0d11cfd50b6e199b03cbc88d3c4ad2ceb

Conflicts:
	src/com/android/camera/data/LocalMediaData.java
	src/com/android/camera/data/RotationTask.java
	src/com/android/camera/widget/FilmstripView.java
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 82da41e..0bc5782 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -54,7 +54,6 @@
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.util.CameraPerformanceTracker;
-import android.util.Log;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.KeyEvent;
@@ -94,6 +93,7 @@
 import com.android.camera.data.PanoramaMetadataLoader;
 import com.android.camera.data.RgbzMetadataLoader;
 import com.android.camera.data.SimpleViewData;
+import com.android.camera.debug.Log;
 import com.android.camera.filmstrip.FilmstripContentPanel;
 import com.android.camera.filmstrip.FilmstripController;
 import com.android.camera.hardware.HardwareSpec;
@@ -146,7 +146,7 @@
         ActionBar.OnMenuVisibilityListener, ShareActionProvider.OnShareTargetSelectedListener,
         OrientationManager.OnOrientationChangeListener {
 
-    private static final String TAG = "CameraActivity";
+    private static final Log.Tag TAG = new Log.Tag("CameraActivity");
 
     private static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE =
             "android.media.action.STILL_IMAGE_CAMERA_SECURE";
@@ -913,7 +913,8 @@
                         mCurrentModule.onPreviewInitialDataReceived();
                         mCameraAppUI.onNewPreviewFrame();
                     }
-                });
+                }
+        );
     }
 
     @Override
@@ -1053,7 +1054,7 @@
                 startPeekAnimation(newData);
             }
         } else {
-            android.util.Log.w(TAG, "Unknown new media with MIME type:" + mimeType + ", uri:" + uri);
+            Log.w(TAG, "Unknown new media with MIME type:" + mimeType + ", uri:" + uri);
         }
     }
 
diff --git a/src/com/android/camera/CameraErrorCallback.java b/src/com/android/camera/CameraErrorCallback.java
index 22f800e..af855d1 100644
--- a/src/com/android/camera/CameraErrorCallback.java
+++ b/src/com/android/camera/CameraErrorCallback.java
@@ -16,14 +16,15 @@
 
 package com.android.camera;
 
-import android.util.Log;
+import com.android.camera.app.CameraManager;
+import com.android.camera.debug.Log;
 
 public class CameraErrorCallback
-        implements android.hardware.Camera.ErrorCallback {
-    private static final String TAG = "CameraErrorCallback";
+        implements CameraManager.CameraErrorCallback {
+    private static final Log.Tag TAG = new Log.Tag("CamErrCallback");
 
     @Override
-    public void onError(int error, android.hardware.Camera camera) {
+    public void onError(int error, CameraManager.CameraProxy camera) {
         Log.e(TAG, "Got camera error callback. error=" + error);
         if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
             // We are not sure about the current state of the app (in preview or
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 554e32d..3caef3b 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -20,24 +20,13 @@
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.hardware.Camera.CameraInfo;
 import android.hardware.Camera.Parameters;
-import android.hardware.Camera.Size;
-import android.media.CamcorderProfile;
-import android.util.Log;
 
 import com.android.camera.app.AppController;
-import com.android.camera.settings.SettingsManager;
-import com.android.camera.util.ApiHelper;
-import com.android.camera.util.CameraUtil;
-import com.android.camera.util.GcamHelper;
+import com.android.camera.debug.Log;
 import com.android.camera2.R;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
 /**
  *  Provides utilities and keys for Camera settings.
  *  TODO: deprecate once all modules are using SettingsManager.
@@ -79,40 +68,13 @@
      */
     public static final int CURRENT_VERSION = 1;
 
-    private static final String TAG = "CameraSettings";
+    private static final Log.Tag TAG = new Log.Tag("CameraSettings");
 
     private final AppController mActivityController;
-    private final Context mContext;
-    private final Parameters mParameters;
-    private final CameraInfo[] mCameraInfo;
-    private final int mCameraId;
-    private final SettingsManager mSettingsManager;
 
     public CameraSettings(AppController app, Parameters parameters,
                           int cameraId, CameraInfo[] cameraInfo) {
         mActivityController = app;
-        mContext = app.getAndroidContext();
-        mParameters = parameters;
-        mCameraId = cameraId;
-        mCameraInfo = cameraInfo;
-        mSettingsManager = mActivityController.getSettingsManager();
-    }
-
-    public static String getSupportedHighestVideoQuality(int cameraId,
-            String defaultQuality) {
-        // When launching the camera app first time, we will set the video quality
-        // to the first one (i.e. highest quality) in the supported list
-        List<String> supported = getSupportedVideoQuality(cameraId);
-        if (supported == null) {
-            Log.e(TAG, "No supported video quality is found");
-            return defaultQuality;
-        }
-        return supported.get(0);
-    }
-
-    public static void removePreferenceFromScreen(
-            PreferenceGroup group, String key) {
-        removePreference(group, key);
     }
 
     public static int getMaxVideoDuration(Context context) {
@@ -124,203 +86,6 @@
         return duration;
     }
 
-    private void initPreference(PreferenceGroup group) {
-        ListPreference videoQuality = group.findPreference(KEY_VIDEO_QUALITY);
-        ListPreference timeLapseInterval = group.findPreference(KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL);
-        ListPreference pictureSize = group.findPreference(KEY_PICTURE_SIZE);
-        ListPreference whiteBalance =  group.findPreference(KEY_WHITE_BALANCE);
-        ListPreference sceneMode = group.findPreference(KEY_SCENE_MODE);
-        ListPreference flashMode = group.findPreference(KEY_FLASH_MODE);
-        ListPreference focusMode = group.findPreference(KEY_FOCUS_MODE);
-        IconListPreference exposure =
-                (IconListPreference) group.findPreference(KEY_EXPOSURE);
-        IconListPreference cameraIdPref =
-                (IconListPreference) group.findPreference(KEY_CAMERA_ID);
-        ListPreference videoFlashMode =
-                group.findPreference(KEY_VIDEOCAMERA_FLASH_MODE);
-        ListPreference videoEffect = group.findPreference(KEY_VIDEO_EFFECT);
-        ListPreference cameraHdr = group.findPreference(KEY_CAMERA_HDR);
-        ListPreference cameraHdrPlus = group.findPreference(KEY_CAMERA_HDR_PLUS);
-
-        // Since the screen could be loaded from different resources, we need
-        // to check if the preference is available here
-        if (videoQuality != null) {
-            filterUnsupportedOptions(group, videoQuality, getSupportedVideoQuality(mCameraId));
-        }
-
-        if (pictureSize != null) {
-            filterUnsupportedOptions(group, pictureSize, sizeListToStringList(
-                    mParameters.getSupportedPictureSizes()));
-            filterSimilarPictureSize(group, pictureSize);
-        }
-        if (whiteBalance != null) {
-            filterUnsupportedOptions(group,
-                    whiteBalance, mParameters.getSupportedWhiteBalance());
-        }
-        if (sceneMode != null) {
-            filterUnsupportedOptions(group,
-                    sceneMode, mParameters.getSupportedSceneModes());
-        }
-        if (flashMode != null) {
-            filterUnsupportedOptions(group,
-                    flashMode, mParameters.getSupportedFlashModes());
-        }
-        if (focusMode != null) {
-            if (!CameraUtil.isFocusAreaSupported(mParameters)) {
-                filterUnsupportedOptions(group,
-                        focusMode, mParameters.getSupportedFocusModes());
-            } else {
-                // Remove the focus mode if we can use tap-to-focus.
-                removePreference(group, focusMode.getKey());
-            }
-        }
-        if (videoFlashMode != null) {
-            filterUnsupportedOptions(group,
-                    videoFlashMode, mParameters.getSupportedFlashModes());
-        }
-        if (exposure != null) {
-            buildExposureCompensation(group, exposure);
-        }
-        if (cameraIdPref != null) {
-            buildCameraId(group, cameraIdPref);
-        }
-
-        if (timeLapseInterval != null) {
-            resetIfInvalid(timeLapseInterval);
-        }
-        if (videoEffect != null) {
-            filterUnsupportedOptions(group, videoEffect, null);
-        }
-        if (cameraHdr != null && (!ApiHelper.HAS_CAMERA_HDR
-                || !CameraUtil.isCameraHdrSupported(mParameters))) {
-            removePreference(group, cameraHdr.getKey());
-        }
-
-        int frontCameraId = mActivityController.getCameraProvider().getFirstFrontCameraId();
-        boolean isFrontCamera = (frontCameraId == mCameraId);
-        if (cameraHdrPlus != null && (!ApiHelper.HAS_CAMERA_HDR_PLUS ||
-                !GcamHelper.hasGcamCapture() || isFrontCamera)) {
-            removePreference(group, cameraHdrPlus.getKey());
-        }
-    }
-
-    private void buildExposureCompensation(
-            PreferenceGroup group, IconListPreference exposure) {
-        int max = mParameters.getMaxExposureCompensation();
-        int min = mParameters.getMinExposureCompensation();
-        if (max == 0 && min == 0) {
-            removePreference(group, exposure.getKey());
-            return;
-        }
-        float step = mParameters.getExposureCompensationStep();
-
-        // show only integer values for exposure compensation
-        int maxValue = Math.min(3, (int) Math.floor(max * step));
-        int minValue = Math.max(-3, (int) Math.ceil(min * step));
-        String explabel = mContext.getResources().getString(R.string.pref_exposure_label);
-        CharSequence entries[] = new CharSequence[maxValue - minValue + 1];
-        CharSequence entryValues[] = new CharSequence[maxValue - minValue + 1];
-        CharSequence labels[] = new CharSequence[maxValue - minValue + 1];
-        int[] icons = new int[maxValue - minValue + 1];
-        TypedArray iconIds = mContext.getResources().obtainTypedArray(
-                R.array.pref_camera_exposure_icons);
-        for (int i = minValue; i <= maxValue; ++i) {
-            entryValues[i - minValue] = Integer.toString(Math.round(i / step));
-            StringBuilder builder = new StringBuilder();
-            if (i > 0) {
-                builder.append('+');
-            }
-            entries[i - minValue] = builder.append(i).toString();
-            labels[i - minValue] = explabel + " " + builder.toString();
-            icons[i - minValue] = iconIds.getResourceId(3 + i, 0);
-        }
-        exposure.setUseSingleIcon(true);
-        exposure.setEntries(entries);
-        exposure.setLabels(labels);
-        exposure.setEntryValues(entryValues);
-        exposure.setLargeIconIds(icons);
-    }
-
-    private void buildCameraId(
-            PreferenceGroup group, IconListPreference preference) {
-        int numOfCameras = mCameraInfo.length;
-        if (numOfCameras < 2) {
-            removePreference(group, preference.getKey());
-            return;
-        }
-
-        CharSequence[] entryValues = new CharSequence[numOfCameras];
-        for (int i = 0; i < numOfCameras; ++i) {
-            entryValues[i] = "" + i;
-        }
-        preference.setEntryValues(entryValues);
-    }
-
-    private static boolean removePreference(PreferenceGroup group, String key) {
-        for (int i = 0, n = group.size(); i < n; i++) {
-            CameraPreference child = group.get(i);
-            if (child instanceof PreferenceGroup) {
-                if (removePreference((PreferenceGroup) child, key)) {
-                    return true;
-                }
-            }
-            if (child instanceof ListPreference &&
-                    ((ListPreference) child).getKey().equals(key)) {
-                group.removePreference(i);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void filterUnsupportedOptions(PreferenceGroup group,
-            ListPreference pref, List<String> supported) {
-        if (pref == null) {
-            return;
-        }
-
-        // Remove the preference if the parameter is not supported or there is
-        // only one options for the settings.
-        if (supported == null || supported.size() <= 1) {
-            removePreference(group, pref.getKey());
-            return;
-        }
-
-        pref.filterUnsupported(supported);
-        if (pref.getEntries().length <= 1) {
-            removePreference(group, pref.getKey());
-            return;
-        }
-
-        resetIfInvalid(pref);
-    }
-
-    private void filterSimilarPictureSize(PreferenceGroup group,
-            ListPreference pref) {
-        pref.filterDuplicated();
-        if (pref.getEntries().length <= 1) {
-            removePreference(group, pref.getKey());
-            return;
-        }
-        resetIfInvalid(pref);
-    }
-
-    private void resetIfInvalid(ListPreference pref) {
-        // Set the value to the first entry if it is invalid.
-        String value = mSettingsManager.getValueFromPreference(pref);
-        if (pref.findIndexOfValue(value) == NOT_FOUND) {
-            mSettingsManager.setValueIndexFromPreference(pref, 0);
-        }
-    }
-
-    private static List<String> sizeListToStringList(List<Size> sizes) {
-        ArrayList<String> list = new ArrayList<String>();
-        for (Size size : sizes) {
-            list.add(String.format(Locale.ENGLISH, "%dx%d", size.width, size.height));
-        }
-        return list;
-    }
-
     /**
      * Upgrade the preferences file from previous older versions to the one we
      * are using. No-op if the versions match.
@@ -382,31 +147,4 @@
         editor.putString(KEY_CAMERA_ID, Integer.toString(cameraId));
         editor.apply();
     }
-
-    public static int readExposure(ComboPreferences preferences) {
-        String exposure = preferences.getString(
-                CameraSettings.KEY_EXPOSURE,
-                EXPOSURE_DEFAULT_VALUE);
-        try {
-            return Integer.parseInt(exposure);
-        } catch (Exception ex) {
-            Log.e(TAG, "Invalid exposure: " + exposure);
-        }
-        return 0;
-    }
-
-    private static ArrayList<String> getSupportedVideoQuality(int cameraId) {
-        ArrayList<String> supported = new ArrayList<String>();
-        // Check for supported quality
-        if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_1080P)) {
-            supported.add(Integer.toString(CamcorderProfile.QUALITY_1080P));
-        }
-        if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_720P)) {
-            supported.add(Integer.toString(CamcorderProfile.QUALITY_720P));
-        }
-        if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_480P)) {
-            supported.add(Integer.toString(CamcorderProfile.QUALITY_480P));
-        }
-        return supported;
-    }
 }
diff --git a/src/com/android/camera/DisableCameraReceiver.java b/src/com/android/camera/DisableCameraReceiver.java
index 3517405..aea6ec5 100644
--- a/src/com/android/camera/DisableCameraReceiver.java
+++ b/src/com/android/camera/DisableCameraReceiver.java
@@ -22,13 +22,14 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.hardware.Camera.CameraInfo;
-import android.util.Log;
+
+import com.android.camera.debug.Log;
 
 // We want to disable camera-related activities if there is no camera. This
 // receiver runs when BOOT_COMPLETED intent is received. After running once
 // this receiver will be disabled, so it will not run again.
 public class DisableCameraReceiver extends BroadcastReceiver {
-    private static final String TAG = "DisableCameraReceiver";
+    private static final Log.Tag TAG = new Log.Tag("DisableCamRcver");
     private static final boolean CHECK_BACK_CAMERA_ONLY = true;
     private static final String ACTIVITIES[] = {
         "com.android.camera.CameraLauncher",
diff --git a/src/com/android/camera/Exif.java b/src/com/android/camera/Exif.java
index 91aca45..fba1d0f 100644
--- a/src/com/android/camera/Exif.java
+++ b/src/com/android/camera/Exif.java
@@ -16,14 +16,13 @@
 
 package com.android.camera;
 
-import android.util.Log;
-
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 
 import java.io.IOException;
 
 public class Exif {
-    private static final String TAG = "CameraExif";
+    private static final Log.Tag TAG = new Log.Tag("CameraExif");
 
     public static ExifInterface getExif(byte[] jpegData) {
         ExifInterface exif = new ExifInterface();
diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java
index 8fe8e64..0f41da3 100644
--- a/src/com/android/camera/FocusOverlayManager.java
+++ b/src/com/android/camera/FocusOverlayManager.java
@@ -26,8 +26,8 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.util.Log;
 
+import com.android.camera.debug.Log;
 import com.android.camera.settings.SettingsManager;
 import com.android.camera.ui.PreviewStatusListener;
 import com.android.camera.util.CameraUtil;
@@ -59,7 +59,7 @@
  *     to change metering area.
  */
 public class FocusOverlayManager implements PreviewStatusListener.PreviewAreaChangedListener {
-    private static final String TAG = "FocusOverlayManager";
+    private static final Log.Tag TAG = new Log.Tag("FocusOverlayMgr");
 
     private static final int RESET_TOUCH_FOCUS = 0;
     private static final int RESET_TOUCH_FOCUS_DELAY = 4000;
diff --git a/src/com/android/camera/ListPreference.java b/src/com/android/camera/ListPreference.java
index 1f02159..c192d34 100644
--- a/src/com/android/camera/ListPreference.java
+++ b/src/com/android/camera/ListPreference.java
@@ -16,27 +16,26 @@
 
 package com.android.camera;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.TypedValue;
 
-import com.android.camera.settings.SettingsManager;
+import com.android.camera.debug.Log;
 import com.android.camera.util.CameraUtil;
 import com.android.camera.util.UsageStatistics;
 import com.android.camera2.R;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * A type of <code>CameraPreference</code> whose number of possible values
  * is limited.
  */
 public class ListPreference extends CameraPreference {
-    private static final String TAG = "ListPreference";
+    private static final Log.Tag TAG = new Log.Tag("ListPreference");
     private final String mKey;
     private String mValue;
     private final CharSequence[] mDefaultValues;
diff --git a/src/com/android/camera/MediaSaverImpl.java b/src/com/android/camera/MediaSaverImpl.java
index f7e7736..029e9c3 100644
--- a/src/com/android/camera/MediaSaverImpl.java
+++ b/src/com/android/camera/MediaSaverImpl.java
@@ -23,9 +23,9 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.provider.MediaStore.Video;
-import android.util.Log;
 
 import com.android.camera.app.MediaSaver;
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 
 import java.io.File;
@@ -34,7 +34,7 @@
  * A class implementing {@link com.android.camera.app.MediaSaver}.
  */
 public class MediaSaverImpl implements MediaSaver {
-    private static final String TAG = "MediaSaverImpl";
+    private static final Log.Tag TAG = new Log.Tag("MediaSaverImpl");
     private static final String VIDEO_BASE_URI = "content://media/external/video/media";
 
     /** The memory limit for unsaved image is 20MB. */
diff --git a/src/com/android/camera/OnScreenHint.java b/src/com/android/camera/OnScreenHint.java
index f47d9d8..b6bb71f 100644
--- a/src/com/android/camera/OnScreenHint.java
+++ b/src/com/android/camera/OnScreenHint.java
@@ -25,6 +25,7 @@
 import android.view.WindowManager;
 import android.widget.TextView;
 
+import com.android.camera.debug.Log;
 import com.android.camera2.R;
 
 /**
@@ -40,7 +41,7 @@
  * constructs everything you need and returns a new {@code OnScreenHint} object.
  */
 public class OnScreenHint {
-    static final String TAG = "OnScreenHint";
+    static final Log.Tag TAG = new Log.Tag("OnScreenHint");
 
     int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
     int mX, mY;
diff --git a/src/com/android/camera/OnScreenIndicators.java b/src/com/android/camera/OnScreenIndicators.java
index 64992cf..a99b291 100644
--- a/src/com/android/camera/OnScreenIndicators.java
+++ b/src/com/android/camera/OnScreenIndicators.java
@@ -20,7 +20,6 @@
 import android.content.res.TypedArray;
 import android.hardware.Camera;
 import android.hardware.Camera.Parameters;
-import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
 
diff --git a/src/com/android/camera/PanoProgressBar.java b/src/com/android/camera/PanoProgressBar.java
index 8dfb366..900710f 100644
--- a/src/com/android/camera/PanoProgressBar.java
+++ b/src/com/android/camera/PanoProgressBar.java
@@ -23,9 +23,11 @@
 import android.util.AttributeSet;
 import android.widget.ImageView;
 
+import com.android.camera.debug.Log;
+
 class PanoProgressBar extends ImageView {
     @SuppressWarnings("unused")
-    private static final String TAG = "PanoProgressBar";
+    private static final Log.Tag TAG = new Log.Tag("PanoProgressBar");
     public static final int DIRECTION_NONE = 0;
     public static final int DIRECTION_LEFT = 1;
     public static final int DIRECTION_RIGHT = 2;
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index 22dea88..789337e 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -41,7 +41,6 @@
 import android.os.MessageQueue;
 import android.os.SystemClock;
 import android.provider.MediaStore;
-import android.util.Log;
 import android.view.KeyEvent;
 import android.view.OrientationEventListener;
 import android.view.View;
@@ -59,6 +58,7 @@
 import com.android.camera.app.MediaSaver;
 import com.android.camera.app.MemoryManager;
 import com.android.camera.app.MemoryManager.MemoryListener;
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.exif.ExifTag;
 import com.android.camera.exif.Rational;
@@ -95,7 +95,7 @@
         SettingsManager.OnSettingChangedListener,
         RemoteCameraModule {
 
-    private static final String TAG = "PhotoModule";
+    private static final Log.Tag TAG = new Log.Tag("PhotoModule");
 
     // We number the request code from 1000 to avoid collision with Gallery.
     private static final int REQUEST_CROP = 1000;
@@ -1421,7 +1421,7 @@
             stopFaceDetection();
             mCameraDevice.setZoomChangeListener(null);
             mCameraDevice.setFaceDetectionCallback(null, null);
-            mCameraDevice.setErrorCallback(null);
+            mCameraDevice.setErrorCallback(null, null);
 
             mFaceDetectionStarted = false;
             mActivity.getCameraProvider().releaseCamera(mCameraDevice.getCameraId());
@@ -1485,7 +1485,7 @@
             return;
         }
 
-        mCameraDevice.setErrorCallback(mErrorCallback);
+        mCameraDevice.setErrorCallback(mHandler, mErrorCallback);
         // ICS camera frameworks has a bug. Face detection state is not cleared
         // after taking a picture. Stop the preview to work around it. The bug
         // was fixed in JB.
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 012cce0..9329ca1 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -23,7 +23,6 @@
 import android.hardware.Camera;
 import android.hardware.Camera.Face;
 import android.os.AsyncTask;
-import android.util.Log;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 import android.view.View;
@@ -31,6 +30,7 @@
 
 import com.android.camera.FocusOverlayManager.FocusUI;
 import com.android.camera.app.CameraManager;
+import com.android.camera.debug.Log;
 import com.android.camera.ui.FaceView;
 import com.android.camera.ui.PreviewOverlay;
 import com.android.camera.ui.PreviewStatusListener;
@@ -42,7 +42,7 @@
 public class PhotoUI implements PreviewStatusListener,
     CameraManager.CameraFaceDetectionCallback {
 
-    private static final String TAG = "PhotoUI";
+    private static final Log.Tag TAG = new Log.Tag("PhotoUI");
     private static final int DOWN_SAMPLE_FACTOR = 4;
     private static final float UNSET = 0f;
 
diff --git a/src/com/android/camera/PreviewGestures.java b/src/com/android/camera/PreviewGestures.java
index b6aed2c..8ab4a7f 100644
--- a/src/com/android/camera/PreviewGestures.java
+++ b/src/com/android/camera/PreviewGestures.java
@@ -21,6 +21,7 @@
 import android.view.ScaleGestureDetector;
 import android.view.View;
 
+import com.android.camera.debug.Log;
 import com.android.camera.ui.PieRenderer;
 import com.android.camera.ui.RenderOverlay;
 import com.android.camera.ui.ZoomRenderer;
@@ -32,7 +33,7 @@
 public class PreviewGestures
         implements ScaleGestureDetector.OnScaleGestureListener {
 
-    private static final String TAG = "PreviewGestures";
+    private static final Log.Tag TAG = new Log.Tag("PreviewGestures");
 
     private static final int MODE_NONE = 0;
     private static final int MODE_ZOOM = 2;
diff --git a/src/com/android/camera/SoundClips.java b/src/com/android/camera/SoundClips.java
index e8e5ce7..ac06be8 100644
--- a/src/com/android/camera/SoundClips.java
+++ b/src/com/android/camera/SoundClips.java
@@ -22,10 +22,10 @@
 import android.media.MediaActionSound;
 import android.media.SoundPool;
 import android.os.Build;
-import android.util.Log;
 
-import com.android.camera2.R;
+import com.android.camera.debug.Log;
 import com.android.camera.util.ApiHelper;
+import com.android.camera2.R;
 
 /*
  * This class controls the sound playback according to the API level.
@@ -62,7 +62,7 @@
      */
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private static class MediaActionSoundPlayer implements Player {
-        private static final String TAG = "MediaActionSoundPlayer";
+        private static final Log.Tag TAG = new Log.Tag("MediaActSndPlayer");
         private MediaActionSound mSound;
 
         @Override
@@ -109,7 +109,7 @@
     private static class SoundPoolPlayer implements
             Player, SoundPool.OnLoadCompleteListener {
 
-        private static final String TAG = "SoundPoolPlayer";
+        private static final Log.Tag TAG = new Log.Tag("SoundPoolPlayer");
         private static final int NUM_SOUND_STREAMS = 1;
         private static final int[] SOUND_RES = { // Soundtrack res IDs.
                 R.raw.focus_complete,
diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java
index d7628f2..10fcfcc 100644
--- a/src/com/android/camera/Storage.java
+++ b/src/com/android/camera/Storage.java
@@ -28,9 +28,9 @@
 import android.provider.MediaStore.Images;
 import android.provider.MediaStore.Images.ImageColumns;
 import android.provider.MediaStore.MediaColumns;
-import android.util.Log;
 
 import com.android.camera.data.LocalData;
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.util.ApiHelper;
 import com.android.camera.util.ImageLoader;
@@ -53,7 +53,7 @@
     public static final long UNKNOWN_SIZE = -3L;
     public static final long LOW_STORAGE_THRESHOLD_BYTES = 50000000;
     public static final String CAMERA_SESSION_SCHEME = "camera_session";
-    private static final String TAG = "Storage";
+    private static final Log.Tag TAG = new Log.Tag("Storage");
     private static final String GOOGLE_COM = "google.com";
     private static HashMap<Uri, Uri> sSessionsToContentUris = new HashMap<Uri, Uri>();
     private static HashMap<Uri, byte[]> sSessionsToPlaceholderBytes = new HashMap<Uri, byte[]>();
diff --git a/src/com/android/camera/SurfaceTextureRenderer.java b/src/com/android/camera/SurfaceTextureRenderer.java
index d075cc9..69897ca 100644
--- a/src/com/android/camera/SurfaceTextureRenderer.java
+++ b/src/com/android/camera/SurfaceTextureRenderer.java
@@ -18,7 +18,8 @@
 
 import android.graphics.SurfaceTexture;
 import android.os.Handler;
-import android.util.Log;
+
+import com.android.camera.debug.Log;
 
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGLConfig;
@@ -33,7 +34,7 @@
         public void onDrawFrame(GL10 gl);
     }
 
-    private static final String TAG = "SurfaceTextureRenderer";
+    private static final Log.Tag TAG = new Log.Tag("SurfTexRenderer");
     private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
 
     private EGLConfig mEglConfig;
diff --git a/src/com/android/camera/TextureViewHelper.java b/src/com/android/camera/TextureViewHelper.java
index 37d0b0d..a788aa8 100644
--- a/src/com/android/camera/TextureViewHelper.java
+++ b/src/com/android/camera/TextureViewHelper.java
@@ -19,11 +19,11 @@
 import android.graphics.Matrix;
 import android.graphics.RectF;
 import android.graphics.SurfaceTexture;
-import android.util.Log;
 import android.view.TextureView;
 import android.view.View;
 import android.view.View.OnLayoutChangeListener;
 
+import com.android.camera.debug.Log;
 import com.android.camera.ui.PreviewStatusListener;
 
 import java.util.ArrayList;
@@ -36,7 +36,7 @@
 public class TextureViewHelper implements TextureView.SurfaceTextureListener,
         OnLayoutChangeListener {
 
-    private static final String TAG = "TextureViewHelper";
+    private static final Log.Tag TAG = new Log.Tag("TexViewHelper");
     private static final float UNSET = 0f;
     private TextureView mPreview;
     private int mWidth = 0;
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index a835fab..69e9881 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -46,7 +46,6 @@
 import android.provider.MediaStore;
 import android.provider.MediaStore.MediaColumns;
 import android.provider.MediaStore.Video;
-import android.util.Log;
 import android.view.KeyEvent;
 import android.view.OrientationEventListener;
 import android.view.View;
@@ -62,6 +61,7 @@
 import com.android.camera.app.MediaSaver;
 import com.android.camera.app.MemoryManager;
 import com.android.camera.app.MemoryManager.MemoryListener;
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.hardware.HardwareSpec;
 import com.android.camera.hardware.HardwareSpecImpl;
@@ -90,7 +90,7 @@
     MediaRecorder.OnErrorListener,
     MediaRecorder.OnInfoListener, FocusOverlayManager.Listener {
 
-    private static final String TAG = "VideoModule";
+    private static final Log.Tag TAG = new Log.Tag("VideoModule");
 
     // Messages defined for the UI thread handler.
     private static final int MSG_CHECK_DISPLAY_ROTATION = 4;
@@ -847,7 +847,7 @@
             return;
         }
 
-        mCameraDevice.setErrorCallback(mErrorCallback);
+        mCameraDevice.setErrorCallback(mHandler, mErrorCallback);
         if (mPreviewing == true) {
             stopPreview();
         }
@@ -916,7 +916,7 @@
             return;
         }
         mCameraDevice.setZoomChangeListener(null);
-        mCameraDevice.setErrorCallback(null);
+        mCameraDevice.setErrorCallback(null, null);
         mActivity.getCameraProvider().releaseCamera(mCameraDevice.getCameraId());
         mCameraDevice = null;
         mPreviewing = false;
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index ef10d45..db965db 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -20,7 +20,6 @@
 import android.graphics.Point;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera.Parameters;
-import android.util.Log;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 import android.view.View;
@@ -29,17 +28,17 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.camera.debug.Log;
 import com.android.camera.ui.FocusOverlay;
 import com.android.camera.ui.PreviewOverlay;
 import com.android.camera.ui.PreviewStatusListener;
 import com.android.camera.ui.RotateLayout;
-import com.android.camera.util.CameraUtil;
 import com.android.camera2.R;
 
 import java.util.List;
 
 public class VideoUI implements PreviewStatusListener {
-    private static final String TAG = "VideoUI";
+    private static final Log.Tag TAG = new Log.Tag("VideoUI");
 
     private final static float UNSET = 0f;
     private final PreviewOverlay mPreviewOverlay;
diff --git a/src/com/android/camera/app/AndroidCameraManagerImpl.java b/src/com/android/camera/app/AndroidCameraManagerImpl.java
index 359a9ee..5aacf41 100644
--- a/src/com/android/camera/app/AndroidCameraManagerImpl.java
+++ b/src/com/android/camera/app/AndroidCameraManagerImpl.java
@@ -34,10 +34,9 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
-import android.util.Log;
 import android.view.SurfaceHolder;
 
-import com.android.camera.app.CameraManager.CameraExceptionCallback;
+import com.android.camera.debug.Log;
 
 import java.io.IOException;
 import java.util.LinkedList;
@@ -47,7 +46,7 @@
  * A class to implement {@link CameraManager} of the Android camera framework.
  */
 class AndroidCameraManagerImpl implements CameraManager {
-    private static final String TAG = "AndroidCameraManagerImpl";
+    private static final Log.Tag TAG = new Log.Tag("AndroidCamMgrImpl");
     private static final long CAMERA_OPERATION_TIMEOUT_MS = 2500;
     private static final long MAX_MESSAGE_QUEUE_LENGTH = 256;
 
@@ -687,7 +686,7 @@
      * A class which implements {@link CameraManager.CameraProxy} and
      * camera handler thread.
      */
-    public class AndroidCameraProxyImpl implements CameraManager.CameraProxy {
+    private class AndroidCameraProxyImpl implements CameraManager.CameraProxy {
         private final int mCameraId;
         /* TODO: remove this Camera instance. */
         private final Camera mCamera;
@@ -1029,11 +1028,13 @@
         }
 
         @Override
-        public void setErrorCallback(final ErrorCallback cb) {
+        public void setErrorCallback(final Handler handler, final CameraErrorCallback cb) {
             mDispatchThread.runJob(new Runnable() {
                 @Override
                 public void run() {
-                    mCameraHandler.obtainMessage(SET_ERROR_CALLBACK, cb).sendToTarget();
+                    mCameraHandler.obtainMessage(SET_ERROR_CALLBACK, ErrorCallbackForward
+                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb)
+                    ).sendToTarget();
                 }
             });
         }
@@ -1148,6 +1149,47 @@
         }
     }
 
+    /**
+     * A helper class to forward ErrorCallback to another thread.
+     */
+    private static class ErrorCallbackForward implements Camera.ErrorCallback {
+        private final Handler mHandler;
+        private final CameraProxy mCamera;
+        private final CameraErrorCallback mCallback;
+
+        /**
+         * Returns a new instance of {@link AFCallbackForward}.
+         *
+         * @param handler The handler in which the callback will be invoked in.
+         * @param camera  The {@link CameraProxy} which the callback is from.
+         * @param cb      The callback to be invoked.
+         * @return        The instance of the {@link AFCallbackForward},
+         *                or null if any parameter is null.
+         */
+        public static ErrorCallbackForward getNewInstance(
+                Handler handler, CameraProxy camera, CameraErrorCallback cb) {
+            if (handler == null || camera == null || cb == null) return null;
+            return new ErrorCallbackForward(handler, camera, cb);
+        }
+
+        private ErrorCallbackForward(
+                Handler h, CameraProxy camera, CameraErrorCallback cb) {
+            mHandler = h;
+            mCamera = camera;
+            mCallback = cb;
+        }
+
+        @Override
+        public void onError(final int error, Camera camera) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onError(error, mCamera);
+                }
+            });
+        }
+    }
+
     /** A helper class to forward AutoFocusMoveCallback to another thread. */
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private static class AFMoveCallbackForward implements AutoFocusMoveCallback {
diff --git a/src/com/android/camera/app/CameraAppUI.java b/src/com/android/camera/app/CameraAppUI.java
index 3eca24a..0953b26 100644
--- a/src/com/android/camera/app/CameraAppUI.java
+++ b/src/com/android/camera/app/CameraAppUI.java
@@ -25,7 +25,6 @@
 import android.graphics.SurfaceTexture;
 import android.hardware.display.DisplayManager;
 import android.util.CameraPerformanceTracker;
-import android.util.Log;
 import android.view.GestureDetector;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -39,6 +38,7 @@
 import com.android.camera.ButtonManager;
 import com.android.camera.ShutterButton;
 import com.android.camera.TextureViewHelper;
+import com.android.camera.debug.Log;
 import com.android.camera.filmstrip.FilmstripContentPanel;
 import com.android.camera.hardware.HardwareSpec;
 import com.android.camera.module.ModuleController;
@@ -406,7 +406,7 @@
     }
 
 
-    private final static String TAG = "CameraAppUI";
+    private final static Log.Tag TAG = new Log.Tag("CameraAppUI");
 
     private final AppController mController;
     private final boolean mIsCaptureIntent;
@@ -698,7 +698,6 @@
      * record a video.
      */
     public void setSwipeEnabled(boolean enabled) {
-        mAppRootView.setSwipeEnabled(enabled);
         mSwipeEnabled = enabled;
     }
 
diff --git a/src/com/android/camera/app/CameraController.java b/src/com/android/camera/app/CameraController.java
index 1b49e25..78edb97 100644
--- a/src/com/android/camera/app/CameraController.java
+++ b/src/com/android/camera/app/CameraController.java
@@ -19,10 +19,10 @@
 import android.content.Context;
 import android.hardware.Camera;
 import android.os.Handler;
-import android.util.Log;
 
 import com.android.camera.CameraDisabledException;
 import com.android.camera.app.CameraManager.CameraExceptionCallback;
+import com.android.camera.debug.Log;
 import com.android.camera.util.CameraUtil;
 
 /**
@@ -31,7 +31,7 @@
  * TODO: Make this class package private.
  */
 public class CameraController implements CameraManager.CameraOpenCallback, CameraProvider {
-    private static final String TAG = "CameraController";
+    private static final Log.Tag TAG = new Log.Tag("CameraController");
     private static final int EMPTY_REQUEST = -1;
     private final Context mContext;
     private CameraManager.CameraOpenCallback mCallbackReceiver;
diff --git a/src/com/android/camera/app/CameraManager.java b/src/com/android/camera/app/CameraManager.java
index dc822c5..6c295c8 100644
--- a/src/com/android/camera/app/CameraManager.java
+++ b/src/com/android/camera/app/CameraManager.java
@@ -19,7 +19,6 @@
 import android.annotation.TargetApi;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
-import android.hardware.Camera.ErrorCallback;
 import android.hardware.Camera.OnZoomChangeListener;
 import android.hardware.Camera.Parameters;
 import android.os.Build;
@@ -53,6 +52,14 @@
 
     /**
      * An interface which wraps
+     * {@link android.hardware.Camera.ErrorCallback}
+     */
+    public interface CameraErrorCallback {
+        public void onError(int error, CameraProxy camera);
+    }
+
+    /**
+     * An interface which wraps
      * {@link android.hardware.Camera.AutoFocusCallback}.
      */
     public interface CameraAFCallback {
@@ -374,10 +381,11 @@
         /**
          * Registers an error callback.
          *
+         * @param handler  The handler on which the callback will be invoked.
          * @param cb The error callback.
          * @see android.hardware.Camera#setErrorCallback(android.hardware.Camera.ErrorCallback)
          */
-        public void setErrorCallback(ErrorCallback cb);
+        public void setErrorCallback(Handler handler, CameraErrorCallback cb);
 
         /**
          * Sets the camera parameters.
diff --git a/src/com/android/camera/app/LegacyLocationProvider.java b/src/com/android/camera/app/LegacyLocationProvider.java
index ed92fdd..0bda5bf 100644
--- a/src/com/android/camera/app/LegacyLocationProvider.java
+++ b/src/com/android/camera/app/LegacyLocationProvider.java
@@ -19,14 +19,15 @@
 import android.content.Context;
 import android.location.Location;
 import android.os.Bundle;
-import android.util.Log;
+
+import com.android.camera.debug.Log;
 
 /**
  * A class that handles legacy (network, gps) location providers, in the event
  * the fused location provider from Google Play Services is unavailable.
  */
 public class LegacyLocationProvider implements LocationProvider {
-    private static final String TAG = "LegacyLocationProvider";
+    private static final Log.Tag TAG = new Log.Tag("LcyLocProvider");
 
     private Context mContext;
     private android.location.LocationManager mLocationManager;
@@ -167,4 +168,4 @@
             return mValid ? mLastLocation : null;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/camera/app/MemoryManagerImpl.java b/src/com/android/camera/app/MemoryManagerImpl.java
index abdc096..a78dd79 100644
--- a/src/com/android/camera/app/MemoryManagerImpl.java
+++ b/src/com/android/camera/app/MemoryManagerImpl.java
@@ -20,9 +20,9 @@
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.util.Log;
 
 import com.android.camera.app.MediaSaver.QueueListener;
+import com.android.camera.debug.Log;
 
 import java.util.LinkedList;
 
@@ -32,7 +32,7 @@
  * TODO: Add GCam signals.
  */
 public class MemoryManagerImpl implements MemoryManager, QueueListener, ComponentCallbacks2 {
-    private static final String TAG = "MemoryManagerImpl";
+    private static final Log.Tag TAG = new Log.Tag("MemoryManagerImpl");
 
     private static final int[] sCriticalStates = new int[] {
             ComponentCallbacks2.TRIM_MEMORY_COMPLETE,
diff --git a/src/com/android/camera/app/ModuleManagerImpl.java b/src/com/android/camera/app/ModuleManagerImpl.java
index 2b64514..593ae76 100644
--- a/src/com/android/camera/app/ModuleManagerImpl.java
+++ b/src/com/android/camera/app/ModuleManagerImpl.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.util.SparseArray;
 
+import com.android.camera.debug.Log;
 import com.android.camera.settings.SettingsManager;
 import com.android.camera2.R;
 
@@ -29,7 +30,7 @@
  * A class which implements {@link com.android.camera.app.ModuleManager}.
  */
 public class ModuleManagerImpl implements ModuleManager {
-    private static final String TAG = "ModuleManagerImpl";
+    private static final Log.Tag TAG = new Log.Tag("ModuleManagerImpl");
 
     private final SparseArray<ModuleAgent> mRegisteredModuleAgents = new
             SparseArray<ModuleAgent>(2);
diff --git a/src/com/android/camera/app/OrientationManagerImpl.java b/src/com/android/camera/app/OrientationManagerImpl.java
index 29c37bb..43f068c 100644
--- a/src/com/android/camera/app/OrientationManagerImpl.java
+++ b/src/com/android/camera/app/OrientationManagerImpl.java
@@ -23,10 +23,10 @@
 import android.content.res.Configuration;
 import android.os.Handler;
 import android.provider.Settings;
-import android.util.Log;
 import android.view.OrientationEventListener;
 import android.view.Surface;
 
+import com.android.camera.debug.Log;
 import com.android.camera.util.ApiHelper;
 
 import java.util.ArrayList;
@@ -38,7 +38,7 @@
  * TODO: make this class package-private
  */
 public class OrientationManagerImpl implements OrientationManager {
-    private static final String TAG = "OrientationManagerImpl";
+    private static final Log.Tag TAG = new Log.Tag("OrientMgrImpl");
 
     // Orientation hysteresis amount used in rounding, in degrees
     private static final int ORIENTATION_HYSTERESIS = 5;
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
index 67a9a0e..766ed3a 100644
--- a/src/com/android/camera/data/CameraDataAdapter.java
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -20,9 +20,9 @@
 import android.content.Context;
 import android.net.Uri;
 import android.os.AsyncTask;
-import android.util.Log;
 import android.view.View;
 
+import com.android.camera.debug.Log;
 import com.android.camera.filmstrip.ImageData;
 
 import java.util.ArrayList;
@@ -33,7 +33,7 @@
  * A {@link LocalDataAdapter} that provides data in the camera folder.
  */
 public class CameraDataAdapter implements LocalDataAdapter {
-    private static final String TAG = "CameraDataAdapter";
+    private static final Log.Tag TAG = new Log.Tag("CameraDataAdapter");
 
     private static final int DEFAULT_DECODE_SIZE = 1600;
 
diff --git a/src/com/android/camera/data/FixedFirstDataAdapter.java b/src/com/android/camera/data/FixedFirstDataAdapter.java
index 05e5274..471fd19 100644
--- a/src/com/android/camera/data/FixedFirstDataAdapter.java
+++ b/src/com/android/camera/data/FixedFirstDataAdapter.java
@@ -21,6 +21,7 @@
 import android.os.AsyncTask;
 import android.view.View;
 
+import com.android.camera.debug.Log;
 import com.android.camera.filmstrip.DataAdapter;
 import com.android.camera.filmstrip.ImageData;
 
@@ -33,7 +34,7 @@
         implements DataAdapter.Listener {
 
     @SuppressWarnings("unused")
-    private static final String TAG = "FixedFirstDataAdapter";
+    private static final Log.Tag TAG = new Log.Tag("FixedFirstDataAdpt");
 
     private LocalData mFirstData;
     private Listener mListener;
diff --git a/src/com/android/camera/data/LocalData.java b/src/com/android/camera/data/LocalData.java
index b434f70..eb3a092 100644
--- a/src/com/android/camera/data/LocalData.java
+++ b/src/com/android/camera/data/LocalData.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.view.View;
 
+import com.android.camera.debug.Log;
 import com.android.camera.filmstrip.ImageData;
 
 import java.util.Comparator;
@@ -33,7 +34,7 @@
  * can guarantee thread safety for LocalData.
  */
 public interface LocalData extends ImageData {
-    static final String TAG = "LocalData";
+    static final Log.Tag TAG = new Log.Tag("LocalData");
 
     public static final String MIME_TYPE_JPEG = "image/jpeg";
 
diff --git a/src/com/android/camera/data/LocalDataUtil.java b/src/com/android/camera/data/LocalDataUtil.java
index 43e5217..f029f45 100644
--- a/src/com/android/camera/data/LocalDataUtil.java
+++ b/src/com/android/camera/data/LocalDataUtil.java
@@ -21,9 +21,8 @@
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.media.MediaMetadataRetriever;
-import android.util.Log;
 
-import com.android.camera.session.PlaceholderManager;
+import com.android.camera.debug.Log;
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -37,7 +36,7 @@
  */
 public class LocalDataUtil {
 
-    private static final String TAG = "LocalDataUtil";
+    private static final Log.Tag TAG = new Log.Tag("LocalDataUtil");
 
     /**
      * @param mimeType The MIME type to check.
diff --git a/src/com/android/camera/data/LocalMediaData.java b/src/com/android/camera/data/LocalMediaData.java
index 19f972b..9841070 100644
--- a/src/com/android/camera/data/LocalMediaData.java
+++ b/src/com/android/camera/data/LocalMediaData.java
@@ -27,12 +27,13 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.MediaStore;
-import android.util.Log;
 import android.view.LayoutInflater;
+import android.view.Gravity;
 import android.view.View;
 import android.widget.ImageView;
 
 import com.android.camera.Storage;
+import com.android.camera.debug.Log;
 import com.android.camera.util.CameraUtil;
 import com.android.camera2.R;
 import com.bumptech.glide.Glide;
@@ -116,8 +117,7 @@
                     result.add(data);
                 } else {
                     final int dataIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
-                    Log.e(TAG, "Error loading data:"
-                            + cursor.getString(dataIndex));
+                    Log.e(TAG, "Error loading data:" + cursor.getString(dataIndex));
                 }
             }
 
@@ -307,7 +307,7 @@
     }
 
     public static final class PhotoData extends LocalMediaData {
-        private static final String TAG = "PhotoData";
+        private static final Log.Tag TAG = new Log.Tag("PhotoData");
 
         public static final int COL_ID = 0;
         public static final int COL_TITLE = 1;
diff --git a/src/com/android/camera/data/MediaDetails.java b/src/com/android/camera/data/MediaDetails.java
index dd4c147..c1d6ccd 100644
--- a/src/com/android/camera/data/MediaDetails.java
+++ b/src/com/android/camera/data/MediaDetails.java
@@ -17,9 +17,9 @@
 package com.android.camera.data;
 
 import android.content.Context;
-import android.util.Log;
 import android.util.SparseIntArray;
 
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.exif.ExifTag;
 import com.android.camera2.R;
@@ -32,7 +32,7 @@
 
 public class MediaDetails implements Iterable<Entry<Integer, Object>> {
     @SuppressWarnings("unused")
-    private static final String TAG = "MediaDetails";
+    private static final Log.Tag TAG = new Log.Tag("MediaDetails");
 
     private TreeMap<Integer, Object> mDetails = new TreeMap<Integer, Object>();
     private SparseIntArray mUnits = new SparseIntArray();
diff --git a/src/com/android/camera/data/RotationTask.java b/src/com/android/camera/data/RotationTask.java
new file mode 100644
index 0000000..8ac9a94
--- /dev/null
+++ b/src/com/android/camera/data/RotationTask.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera.data;
+
+import android.app.ProgressDialog;
+import android.content.ContentValues;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.provider.MediaStore.Images;
+
+import com.android.camera.data.LocalMediaData.PhotoData;
+import com.android.camera.debug.Log;
+import com.android.camera.exif.ExifInterface;
+import com.android.camera.exif.ExifTag;
+import com.android.camera2.R;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * RotationTask can be used to rotate a {@link LocalData} by updating the exif
+ * data from jpeg file. Note that only {@link PhotoData}  can be rotated.
+ */
+public class RotationTask extends AsyncTask<LocalData, Void, LocalData> {
+    private static final Log.Tag TAG = new Log.Tag("RotationTask");
+    private final Context mContext;
+    private final LocalDataAdapter mAdapter;
+    private final int mCurrentDataId;
+    private final boolean mClockwise;
+    private ProgressDialog mProgress;
+
+    public RotationTask(Context context, LocalDataAdapter adapter,
+            int currentDataId, boolean clockwise) {
+        mContext = context;
+        mAdapter = adapter;
+        mCurrentDataId = currentDataId;
+        mClockwise = clockwise;
+    }
+
+    @Override
+    protected void onPreExecute() {
+        // Show a progress bar since the rotation could take long.
+        mProgress = new ProgressDialog(mContext);
+        int titleStringId = mClockwise ? R.string.rotate_right : R.string.rotate_left;
+        mProgress.setTitle(mContext.getString(titleStringId));
+        mProgress.setMessage(mContext.getString(R.string.please_wait));
+        mProgress.setCancelable(false);
+        mProgress.show();
+    }
+
+    @Override
+    protected LocalData doInBackground(LocalData... data) {
+        return rotateInJpegExif(data[0]);
+    }
+
+    /**
+     * Rotates the image by updating the exif. Done in background thread.
+     * The worst case is the whole file needed to be re-written with
+     * modified exif data.
+     *
+     * @return A new {@link LocalData} object which containing the new info.
+     */
+    private LocalData rotateInJpegExif(LocalData data) {
+        if (!(data instanceof PhotoData)) {
+            Log.w(TAG, "Rotation can only happen on PhotoData.");
+            return null;
+        }
+
+        PhotoData imageData = (PhotoData) data;
+        int originRotation = imageData.getRotation();
+        int finalRotationDegrees;
+        if (mClockwise) {
+            finalRotationDegrees = (originRotation + 90) % 360;
+        } else {
+            finalRotationDegrees = (originRotation + 270) % 360;
+        }
+
+        String filePath = imageData.getPath();
+        ContentValues values = new ContentValues();
+        boolean success = false;
+        int newOrientation = 0;
+        if (imageData.getMimeType().equalsIgnoreCase(LocalData.MIME_TYPE_JPEG)) {
+            ExifInterface exifInterface = new ExifInterface();
+            ExifTag tag = exifInterface.buildTag(
+                    ExifInterface.TAG_ORIENTATION,
+                    ExifInterface.getOrientationValueForRotation(
+                            finalRotationDegrees));
+            if (tag != null) {
+                exifInterface.setTag(tag);
+                try {
+                    // Note: This only works if the file already has some EXIF.
+                    exifInterface.forceRewriteExif(filePath);
+                    long fileSize = new File(filePath).length();
+                    values.put(Images.Media.SIZE, fileSize);
+                    newOrientation = finalRotationDegrees;
+                    success = true;
+                } catch (FileNotFoundException e) {
+                    Log.w(TAG, "Cannot find file to set exif: " + filePath);
+                } catch (IOException e) {
+                    Log.w(TAG, "Cannot set exif data: " + filePath);
+                }
+            } else {
+                Log.w(TAG, "Cannot build tag: " + ExifInterface.TAG_ORIENTATION);
+            }
+        }
+
+        PhotoData result = null;
+        if (success) {
+            // MediaStore using SQLite is thread safe.
+            values.put(Images.Media.ORIENTATION, finalRotationDegrees);
+            mContext.getContentResolver().update(imageData.getUri(),
+                    values, null, null);
+            double[] latLong = data.getLatLong();
+            double latitude = 0;
+            double longitude = 0;
+            if (latLong != null) {
+                latitude = latLong[0];
+                longitude = latLong[1];
+            }
+
+            result = new PhotoData(data.getContentId(), data.getTitle(),
+                    data.getMimeType(), data.getDateTaken(), data.getDateModified(),
+                    data.getPath(), newOrientation, imageData.getWidth(),
+                    imageData.getHeight(), data.getSizeInBytes(), latitude, longitude);
+        }
+
+        return result;
+    }
+
+    @Override
+    protected void onPostExecute(LocalData result) {
+        mProgress.dismiss();
+        if (result != null) {
+            mAdapter.updateData(mCurrentDataId, result);
+        }
+    }
+}
diff --git a/src/com/android/camera/data/SimpleViewData.java b/src/com/android/camera/data/SimpleViewData.java
index 3692e2c..74f1073 100644
--- a/src/com/android/camera/data/SimpleViewData.java
+++ b/src/com/android/camera/data/SimpleViewData.java
@@ -20,9 +20,9 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
-import android.util.Log;
 import android.view.View;
 
+import com.android.camera.debug.Log;
 import com.android.camera.filmstrip.ImageData;
 
 import java.util.UUID;
@@ -31,7 +31,7 @@
  * A LocalData that does nothing but only shows a view.
  */
 public class SimpleViewData implements LocalData {
-    private static final String TAG = "SimpleViewData";
+    private static final Log.Tag TAG = new Log.Tag("SimpleViewData");
     private static final String SIMPLE_VIEW_URI_SCHEME = "simple_view_data";
 
     private final int mWidth;
diff --git a/src/com/android/camera/data/VideoRotationMetadataLoader.java b/src/com/android/camera/data/VideoRotationMetadataLoader.java
index 608ceee..8269f9e 100644
--- a/src/com/android/camera/data/VideoRotationMetadataLoader.java
+++ b/src/com/android/camera/data/VideoRotationMetadataLoader.java
@@ -1,10 +1,11 @@
 package com.android.camera.data;
 
 import android.media.MediaMetadataRetriever;
-import android.util.Log;
+
+import com.android.camera.debug.Log;
 
 public class VideoRotationMetadataLoader {
-    private static final String TAG = "VideoRotationMetadataLoader";
+    private static final Log.Tag TAG = new Log.Tag("VidRotDataLoader");
     private static final String ROTATION_KEY = "metadata_video_rotation";
     private static final String WIDTH_KEY = "metadata_video_width";
     private static final String HEIGHT_KEY = "metadata_video_height";
diff --git a/src/com/android/camera/debug/Config.java b/src/com/android/camera/debug/Config.java
new file mode 100644
index 0000000..499dfd6
--- /dev/null
+++ b/src/com/android/camera/debug/Config.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera.debug;
+
+/**
+ * An interface which defines the debug configurations.
+ */
+public interface Config {
+
+    /** @return {@code true} to switch on debug settings. */
+    boolean isDebugging();
+
+    /** @return {@code true} to enable isDebugging level logs. */
+    boolean logDebug();
+
+    /** @return {@code true} to enable ERROR level logs. */
+    boolean logError();
+
+    /** @return {@code true} to enable INFO level logs. */
+    boolean logInfo();
+
+    /** @return {@code true} to enable VERBOSE level logs. */
+    boolean logVerbose();
+
+    /** @return {@code true} to enable WARN level logs. */
+    boolean logWarn();
+}
diff --git a/src/com/android/camera/debug/Configurations.java b/src/com/android/camera/debug/Configurations.java
new file mode 100644
index 0000000..5e69983
--- /dev/null
+++ b/src/com/android/camera/debug/Configurations.java
@@ -0,0 +1,111 @@
+package com.android.camera.debug;
+
+/**
+ * Predefined {@link com.android.camera.debug.Config}s.
+ */
+public enum Configurations implements Config {
+    /**
+     * Enables error logs and disable all others.
+     */
+    RELEASE {
+        @Override
+        public boolean isDebugging() {
+            return false;
+        }
+
+        @Override
+        public boolean logDebug() {
+            return false;
+        }
+
+        @Override
+        public boolean logError() {
+            return true;
+        }
+
+        @Override
+        public boolean logInfo() {
+            return false;
+        }
+
+        @Override
+        public boolean logVerbose() {
+            return false;
+        }
+
+        @Override
+        public boolean logWarn() {
+            return false;
+        }
+    },
+
+    /**
+     * Enables everything.
+     */
+    EVERYTHING_ON {
+        @Override
+        public boolean isDebugging() {
+            return true;
+        }
+
+        @Override
+        public boolean logDebug() {
+            return true;
+        }
+
+        @Override
+        public boolean logError() {
+            return true;
+        }
+
+        @Override
+        public boolean logInfo() {
+            return true;
+        }
+
+        @Override
+        public boolean logVerbose() {
+            return true;
+        }
+
+        @Override
+        public boolean logWarn() {
+            return true;
+        }
+    },
+
+    /**
+     * Logs everything but disables debug settings.
+     */
+    LOG_ALL_NO_DEBUG {
+        @Override
+        public boolean isDebugging() {
+            return false;
+        }
+
+        @Override
+        public boolean logDebug() {
+            return true;
+        }
+
+        @Override
+        public boolean logError() {
+            return true;
+        }
+
+        @Override
+        public boolean logInfo() {
+            return true;
+        }
+
+        @Override
+        public boolean logVerbose() {
+            return true;
+        }
+
+        @Override
+        public boolean logWarn() {
+            return true;
+        }
+    };
+}
diff --git a/src/com/android/camera/debug/CurrentConfig.java b/src/com/android/camera/debug/CurrentConfig.java
new file mode 100644
index 0000000..2ce0dfa
--- /dev/null
+++ b/src/com/android/camera/debug/CurrentConfig.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera.debug;
+
+/**
+ * The default debug configurations.
+ */
+public class CurrentConfig {
+
+    private static final Config sDefaultConfig = Configurations.LOG_ALL_NO_DEBUG;
+    private static Config sCurrentConfig = sDefaultConfig;
+
+    /**
+     * Sets the config to change the debug settings.
+     *
+     * @param config The new config. Sets {@code null} to use the default one.
+     */
+    public static void set(Config config) {
+        sCurrentConfig = (config != null ? config : sDefaultConfig);
+    }
+
+    /** @return The current config. */
+    public static Config get() {
+        return sCurrentConfig;
+    }
+}
diff --git a/src/com/android/camera/debug/DebugCameraProxy.java b/src/com/android/camera/debug/DebugCameraProxy.java
new file mode 100644
index 0000000..936ed8f
--- /dev/null
+++ b/src/com/android/camera/debug/DebugCameraProxy.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera.debug;
+
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.Handler;
+import android.view.SurfaceHolder;
+
+import com.android.camera.app.CameraManager;
+
+/**
+ * A {@link com.android.camera.app.CameraManager.CameraProxy} which wraps the
+ * other and adds logs for all operations.
+ */
+public class DebugCameraProxy implements CameraManager.CameraProxy {
+    private final Log.Tag mTag;
+    private final CameraManager.CameraProxy mProxy;
+
+    /**
+     * Constructor.
+     *
+     * @param tag The tag to be used for logs.
+     * @param proxy The camera proxy to be wrapped.
+     */
+    public DebugCameraProxy(Log.Tag tag, CameraManager.CameraProxy proxy) {
+        mTag = tag;
+        mProxy = proxy;
+    }
+
+    @Override
+    public Camera getCamera() {
+        log("getCamera");
+        return mProxy.getCamera();
+    }
+
+    @Override
+    public int getCameraId() {
+        log("getCameraId: " + mProxy.getCameraId());
+        return mProxy.getCameraId();
+    }
+
+    @Override
+    public void release(boolean synchronous) {
+        log("release " + (synchronous ? "sync" : "async"));
+        mProxy.release(synchronous);
+    }
+
+    @Override
+    public void reconnect(Handler handler, CameraManager.CameraOpenCallback cb) {
+        log("reconnect");
+        mProxy.reconnect(handler, cb);
+    }
+
+    @Override
+    public void unlock() {
+        log("unlock");
+        mProxy.unlock();
+    }
+
+    @Override
+    public void lock() {
+        log("lock");
+        mProxy.lock();
+    }
+
+    @Override
+    public void setPreviewTexture(SurfaceTexture surfaceTexture) {
+        log("setPreviewTexture");
+        mProxy.setPreviewTexture(surfaceTexture);
+    }
+
+    @Override
+    public void setPreviewTextureSync(SurfaceTexture surfaceTexture) {
+        log("setPreviewTextureSync");
+        mProxy.setPreviewTextureSync(surfaceTexture);
+    }
+
+    @Override
+    public void setPreviewDisplay(SurfaceHolder surfaceHolder) {
+        log("setPreviewDisplay");
+        mProxy.setPreviewDisplay(surfaceHolder);
+    }
+
+    @Override
+    public void startPreview() {
+        log("startPreview");
+        mProxy.startPreview();
+    }
+
+    @Override
+    public void startPreviewWithCallback(Handler h, CameraManager.CameraStartPreviewCallback cb) {
+        log("startPreviewWithCallback");
+        mProxy.startPreviewWithCallback(h, cb);
+    }
+
+    @Override
+    public void stopPreview() {
+        log("stopPreview");
+        mProxy.stopPreview();
+    }
+
+    @Override
+    public void setPreviewDataCallback(Handler handler,
+            CameraManager.CameraPreviewDataCallback cb) {
+        log("setPreviewDataCallback");
+        mProxy.setPreviewDataCallback(handler, cb);
+    }
+
+    @Override
+    public void setOneShotPreviewCallback(Handler handler,
+            CameraManager.CameraPreviewDataCallback cb) {
+        log("setOneShotPreviewCallback");
+        mProxy.setOneShotPreviewCallback(handler, cb);
+    }
+
+    @Override
+    public void setPreviewDataCallbackWithBuffer(Handler handler,
+            CameraManager.CameraPreviewDataCallback cb) {
+        log("setPreviewDataCallbackWithBuffer");
+        mProxy.setPreviewDataCallbackWithBuffer(handler, cb);
+    }
+
+    @Override
+    public void addCallbackBuffer(byte[] callbackBuffer) {
+        log("addCallbackBuffer");
+        mProxy.addCallbackBuffer(callbackBuffer);
+    }
+
+    @Override
+    public void autoFocus(Handler handler, CameraManager.CameraAFCallback cb) {
+        log("autoFocus");
+        mProxy.autoFocus(handler, cb);
+    }
+
+    @Override
+    public void cancelAutoFocus() {
+        log("cancelAutoFocus");
+        mProxy.cancelAutoFocus();
+    }
+
+    @Override
+    public void setAutoFocusMoveCallback(Handler handler, CameraManager.CameraAFMoveCallback cb) {
+        log("setAutoFocusMoveCallback");
+        mProxy.setAutoFocusMoveCallback(handler, cb);
+    }
+
+    @Override
+    public void takePicture(Handler handler, CameraManager.CameraShutterCallback shutter,
+            CameraManager.CameraPictureCallback raw, CameraManager.CameraPictureCallback postview,
+            CameraManager.CameraPictureCallback jpeg) {
+        log("takePicture");
+        mProxy.takePicture(handler, shutter, raw, postview, jpeg);
+    }
+
+    @Override
+    public void setDisplayOrientation(int degrees) {
+        log("setDisplayOrientation:" + degrees);
+        mProxy.setDisplayOrientation(degrees);
+    }
+
+    @Override
+    public void setZoomChangeListener(Camera.OnZoomChangeListener listener) {
+        log("setZoomChangeListener");
+        mProxy.setZoomChangeListener(listener);
+    }
+
+    @Override
+    public void setFaceDetectionCallback(Handler handler,
+            CameraManager.CameraFaceDetectionCallback callback) {
+        log("setFaceDetectionCallback");
+        mProxy.setFaceDetectionCallback(handler, callback);
+    }
+
+    @Override
+    public void startFaceDetection() {
+        log("startFaceDetection");
+        mProxy.startFaceDetection();
+    }
+
+    @Override
+    public void stopFaceDetection() {
+        log("stopFaceDetection");
+        mProxy.stopFaceDetection();
+    }
+
+    @Override
+    public void setErrorCallback(Handler handler, CameraManager.CameraErrorCallback cb) {
+        log("setErrorCallback");
+        mProxy.setErrorCallback(handler, cb);
+    }
+
+    @Override
+    public void setParameters(Camera.Parameters params) {
+        log("setParameters");
+        mProxy.setParameters(params);
+    }
+
+    @Override
+    public Camera.Parameters getParameters() {
+        log("getParameters");
+        return mProxy.getParameters();
+    }
+
+    @Override
+    public void refreshParameters() {
+        log("refreshParameters");
+        mProxy.refreshParameters();
+    }
+
+    @Override
+    public void enableShutterSound(boolean enable) {
+        log("enableShutterSound:" + enable);
+        mProxy.enableShutterSound(enable);
+    }
+
+    private void log(String msg) {
+        Log.v(mTag, msg);
+    }
+}
diff --git a/src/com/android/camera/debug/Log.java b/src/com/android/camera/debug/Log.java
new file mode 100644
index 0000000..8c2980d
--- /dev/null
+++ b/src/com/android/camera/debug/Log.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera.debug;
+
+public class Log {
+    public static final String CAMERA_LOGTAG_PREFIX = "CAM_";
+    private static final Log.Tag TAG = new Log.Tag("Log");
+
+    /**
+     * This class restricts the length of the log tag to be less than the
+     * framework limit and also prepends the common tag prefix defined by
+     * {@code CAMERA_LOGTAG_PREFIX}.
+     */
+    public static final class Tag {
+
+        // The length limit from Android framework is 23.
+        private static final int MAX_TAG_LEN = 23 - CAMERA_LOGTAG_PREFIX.length();
+
+        final String mValue;
+
+        public Tag(String tag) {
+            final int lenDiff = tag.length() - MAX_TAG_LEN;
+            if (lenDiff > 0) {
+                w(TAG, "Tag " + tag + " is " + lenDiff + " chars longer than limit.");
+            }
+            mValue = CAMERA_LOGTAG_PREFIX + (lenDiff > 0 ? tag.substring(0, MAX_TAG_LEN) : tag);
+        }
+
+        @Override
+        public String toString() {
+            return mValue;
+        }
+    }
+
+    private interface Logger {
+        void log(Tag tag, String msg);
+        void log(Tag tag, String msg, Throwable tr);
+    }
+
+    private static final Logger SILENT_LOGGER = new Logger() {
+        @Override
+        public void log(Tag tag, String msg) {
+            // Do nothing.
+        }
+
+        @Override
+        public void log(Tag tag, String msg, Throwable tr) {
+            // Do nothing.
+        }
+    };
+
+    private static final Logger LOGGER_D = (!CurrentConfig.get().logDebug() ? SILENT_LOGGER : new Logger() {
+        final int level = android.util.Log.DEBUG;
+
+        @Override
+        public void log(Tag tag, String msg) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.d(tag.toString(), msg);
+            }
+        }
+
+        @Override
+        public void log(Tag tag, String msg, Throwable tr) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.d(tag.toString(), msg, tr);
+            }
+        }
+    });
+
+    private static final Logger LOGGER_E = (!CurrentConfig.get().logError() ? SILENT_LOGGER : new Logger() {
+        final int level = android.util.Log.ERROR;
+
+        @Override
+        public void log(Tag tag, String msg) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.e(tag.toString(), msg);
+            }
+        }
+
+        @Override
+        public void log(Tag tag, String msg, Throwable tr) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.e(tag.toString(), msg, tr);
+            }
+        }
+    });
+
+    private static final Logger LOGGER_I = (!CurrentConfig.get().logInfo() ? SILENT_LOGGER : new Logger() {
+        final int level = android.util.Log.INFO;
+
+        @Override
+        public void log(Tag tag, String msg) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.i(tag.toString(), msg);
+            }
+        }
+
+        @Override
+        public void log(Tag tag, String msg, Throwable tr) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.i(tag.toString(), msg, tr);
+            }
+        }
+    });
+
+    private static final Logger LOGGER_V = (!CurrentConfig.get().logVerbose() ? SILENT_LOGGER : new Logger() {
+        final int level = android.util.Log.VERBOSE;
+
+        @Override
+        public void log(Tag tag, String msg) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.v(tag.toString(), msg);
+            }
+        }
+
+        @Override
+        public void log(Tag tag, String msg, Throwable tr) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.v(tag.toString(), msg, tr);
+            }
+        }
+    });
+
+    private static final Logger LOGGER_W = (!CurrentConfig.get().logWarn() ? SILENT_LOGGER : new Logger() {
+        final int level = android.util.Log.WARN;
+
+        @Override
+        public void log(Tag tag, String msg) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.w(tag.toString(), msg);
+            }
+        }
+
+        @Override
+        public void log(Tag tag, String msg, Throwable tr) {
+            if (isLoggable(tag, level)) {
+                android.util.Log.w(tag.toString(), msg, tr);
+            }
+        }
+    });
+
+
+    public static void d(Tag tag, String msg) {
+        LOGGER_D.log(tag, msg);
+    }
+
+    public static void d(Tag tag, String msg, Throwable tr) {
+        LOGGER_D.log(tag, msg, tr);
+    }
+
+    public static void e(Tag tag, String msg) {
+        LOGGER_E.log(tag, msg);
+    }
+
+    public static void e(Tag tag, String msg, Throwable tr) {
+        LOGGER_E.log(tag, msg, tr);
+    }
+
+    public static void i(Tag tag, String msg) {
+        LOGGER_I.log(tag, msg);
+    }
+
+    public static void i(Tag tag, String msg, Throwable tr) {
+        LOGGER_I.log(tag, msg, tr);
+    }
+
+    public static void v(Tag tag, String msg) {
+        LOGGER_V.log(tag, msg);
+    }
+
+    public static void v(Tag tag, String msg, Throwable tr) {
+        LOGGER_V.log(tag, msg, tr);
+    }
+
+    public static void w(Tag tag, String msg) {
+        LOGGER_W.log(tag, msg);
+    }
+
+    public static void w(Tag tag, String msg, Throwable tr) {
+        LOGGER_W.log(tag, msg, tr);
+    }
+
+    private static boolean isLoggable(Tag tag, int level) {
+        try {
+            return android.util.Log.isLoggable(tag.toString(), level);
+        } catch (IllegalArgumentException ex) {
+            e(TAG, "Tag too long:" + tag);
+            return false;
+        }
+    }
+}
diff --git a/src/com/android/camera/exif/ExifData.java b/src/com/android/camera/exif/ExifData.java
index ed1f349..5a4d019 100644
--- a/src/com/android/camera/exif/ExifData.java
+++ b/src/com/android/camera/exif/ExifData.java
@@ -16,7 +16,7 @@
 
 package com.android.camera.exif;
 
-import android.util.Log;
+import com.android.camera.debug.Log;
 
 import java.io.UnsupportedEncodingException;
 import java.nio.ByteOrder;
@@ -32,7 +32,7 @@
  * @see IfdData
  */
 class ExifData {
-    private static final String TAG = "ExifData";
+    private static final Log.Tag TAG = new Log.Tag("ExifData");
     private static final byte[] USER_COMMENT_ASCII = {
             0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00
     };
diff --git a/src/com/android/camera/exif/ExifModifier.java b/src/com/android/camera/exif/ExifModifier.java
index bed038c..fbb38e3 100644
--- a/src/com/android/camera/exif/ExifModifier.java
+++ b/src/com/android/camera/exif/ExifModifier.java
@@ -16,9 +16,8 @@
 
 package com.android.camera.exif;
 
-import android.util.Log;
+import com.android.camera.debug.Log;
 
-import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
@@ -27,7 +26,7 @@
 import java.util.List;
 
 class ExifModifier {
-    public static final String TAG = "ExifModifier";
+    public static final Log.Tag TAG = new Log.Tag("ExifModifier");
     public static final boolean DEBUG = false;
     private final ByteBuffer mByteBuffer;
     private final ExifData mTagToModified;
diff --git a/src/com/android/camera/exif/ExifOutputStream.java b/src/com/android/camera/exif/ExifOutputStream.java
index 191e828..3c7ed7d 100644
--- a/src/com/android/camera/exif/ExifOutputStream.java
+++ b/src/com/android/camera/exif/ExifOutputStream.java
@@ -16,7 +16,7 @@
 
 package com.android.camera.exif;
 
-import android.util.Log;
+import com.android.camera.debug.Log;
 
 import java.io.BufferedOutputStream;
 import java.io.FilterOutputStream;
@@ -58,7 +58,7 @@
  * </pre>
  */
 class ExifOutputStream extends FilterOutputStream {
-    private static final String TAG = "ExifOutputStream";
+    private static final Log.Tag TAG = new Log.Tag("ExifOutputStream");
     private static final boolean DEBUG = false;
     private static final int STREAMBUFFER_SIZE = 0x00010000; // 64Kb
 
diff --git a/src/com/android/camera/exif/ExifParser.java b/src/com/android/camera/exif/ExifParser.java
index 766268b..3e0cd55 100644
--- a/src/com/android/camera/exif/ExifParser.java
+++ b/src/com/android/camera/exif/ExifParser.java
@@ -16,7 +16,7 @@
 
 package com.android.camera.exif;
 
-import android.util.Log;
+import com.android.camera.debug.Log;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -68,7 +68,7 @@
  */
 class ExifParser {
     private static final boolean LOGV = false;
-    private static final String TAG = "ExifParser";
+    private static final Log.Tag TAG = new Log.Tag("ExifParser");
     /**
      * When the parser reaches a new IFD area. Call {@link #getCurrentIfd()} to
      * know which IFD we are in.
diff --git a/src/com/android/camera/exif/ExifReader.java b/src/com/android/camera/exif/ExifReader.java
index 757e0d3..fea8ff1 100644
--- a/src/com/android/camera/exif/ExifReader.java
+++ b/src/com/android/camera/exif/ExifReader.java
@@ -16,7 +16,7 @@
 
 package com.android.camera.exif;
 
-import android.util.Log;
+import com.android.camera.debug.Log;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -26,7 +26,7 @@
  * {@link ExifData}.
  */
 class ExifReader {
-    private static final String TAG = "ExifReader";
+    private static final Log.Tag TAG = new Log.Tag("ExifReader");
 
     private final ExifInterface mInterface;
 
diff --git a/src/com/android/camera/module/ModulesInfo.java b/src/com/android/camera/module/ModulesInfo.java
index aceed47..b771168 100644
--- a/src/com/android/camera/module/ModulesInfo.java
+++ b/src/com/android/camera/module/ModulesInfo.java
@@ -22,6 +22,7 @@
 import com.android.camera.VideoModule;
 import com.android.camera.app.AppController;
 import com.android.camera.app.ModuleManager;
+import com.android.camera.debug.Log;
 import com.android.camera.util.GcamHelper;
 import com.android.camera.util.PhotoSphereHelper;
 import com.android.camera.util.RefocusHelper;
@@ -32,7 +33,7 @@
  * {@link com.android.camera.app.ModuleManager}.
  */
 public class ModulesInfo {
-    private static final String TAG = "ModulesInfo";
+    private static final Log.Tag TAG = new Log.Tag("ModulesInfo");
 
     public static void setupModules(Context context, ModuleManager moduleManager) {
         int photoModuleId = context.getResources().getInteger(R.integer.camera_mode_photo);
diff --git a/src/com/android/camera/processing/ProcessingService.java b/src/com/android/camera/processing/ProcessingService.java
index 1283574..d59848d 100644
--- a/src/com/android/camera/processing/ProcessingService.java
+++ b/src/com/android/camera/processing/ProcessingService.java
@@ -28,10 +28,10 @@
 import android.os.PowerManager.WakeLock;
 import android.os.Process;
 import android.support.v4.content.LocalBroadcastManager;
-import android.util.Log;
 
 import com.android.camera.app.CameraApp;
 import com.android.camera.app.CameraServices;
+import com.android.camera.debug.Log;
 import com.android.camera.session.CaptureSession;
 import com.android.camera.session.CaptureSession.ProgressListener;
 import com.android.camera.session.CaptureSessionManager;
@@ -70,7 +70,7 @@
         }
     }
 
-    private static final String TAG = "ProcessingService";
+    private static final Log.Tag TAG = new Log.Tag("ProcessingService");
     private static final int THREAD_PRIORITY = Process.THREAD_PRIORITY_DISPLAY;
     private static final int CAMERA_NOTIFICATION_ID = 2;
     private Notification.Builder mNotificationBuilder;
@@ -106,7 +106,7 @@
         // Keep CPU awake while allowing screen and keyboard to switch off.
         PowerManager powerManager = (PowerManager) getSystemService(
                 Context.POWER_SERVICE);
-        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG.toString());
         mWakeLock.acquire();
 
         IntentFilter intentFilter = new IntentFilter();
diff --git a/src/com/android/camera/processing/ProcessingServiceManager.java b/src/com/android/camera/processing/ProcessingServiceManager.java
index ca2ad97..2c7b70a 100644
--- a/src/com/android/camera/processing/ProcessingServiceManager.java
+++ b/src/com/android/camera/processing/ProcessingServiceManager.java
@@ -18,7 +18,8 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.util.Log;
+
+import com.android.camera.debug.Log;
 
 import java.util.LinkedList;
 import java.util.NoSuchElementException;
@@ -31,7 +32,7 @@
  * directly.
  */
 public class ProcessingServiceManager {
-    private static final String TAG = "ProcessingServiceManager";
+    private static final Log.Tag TAG = new Log.Tag("ProcessingSvcMgr");
 
     /** The singleton instance of this manager. */
     private static ProcessingServiceManager sInstance;
diff --git a/src/com/android/camera/session/CaptureSessionManagerImpl.java b/src/com/android/camera/session/CaptureSessionManagerImpl.java
index 10e0d04..d0bc9ce 100644
--- a/src/com/android/camera/session/CaptureSessionManagerImpl.java
+++ b/src/com/android/camera/session/CaptureSessionManagerImpl.java
@@ -23,11 +23,11 @@
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Looper;
-import android.util.Log;
 
 import com.android.camera.app.MediaSaver;
 import com.android.camera.app.MediaSaver.OnMediaSavedListener;
 import com.android.camera.data.LocalData;
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.util.FileUtil;
 
@@ -43,7 +43,7 @@
  */
 public class CaptureSessionManagerImpl implements CaptureSessionManager {
 
-    private static final String TAG = "CaptureSessionManagerImpl";
+    private static final Log.Tag TAG = new Log.Tag("CaptureSessMgrImpl");
     public static final String TEMP_SESSIONS = "TEMP_SESSIONS";
 
     private class CaptureSessionImpl implements CaptureSession {
diff --git a/src/com/android/camera/session/PlaceholderManager.java b/src/com/android/camera/session/PlaceholderManager.java
index 19dd4d6..7403c7f 100644
--- a/src/com/android/camera/session/PlaceholderManager.java
+++ b/src/com/android/camera/session/PlaceholderManager.java
@@ -25,6 +25,7 @@
 import android.provider.MediaStore;
 
 import com.android.camera.Storage;
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.util.CameraUtil;
 
@@ -33,7 +34,7 @@
  * output media item is being produced.
  */
 public class PlaceholderManager {
-    private static final String TAG = "PlaceholderManager";
+    private static final Log.Tag TAG = new Log.Tag("PlaceholderMgr");
 
     private final Context mContext;
 
diff --git a/src/com/android/camera/session/SessionStorageManagerImpl.java b/src/com/android/camera/session/SessionStorageManagerImpl.java
index 8673036..444edcf 100644
--- a/src/com/android/camera/session/SessionStorageManagerImpl.java
+++ b/src/com/android/camera/session/SessionStorageManagerImpl.java
@@ -17,8 +17,8 @@
 package com.android.camera.session;
 
 import android.content.Context;
-import android.util.Log;
 
+import com.android.camera.debug.Log;
 import com.android.camera.util.FileUtil;
 
 import java.io.File;
@@ -29,7 +29,7 @@
  * Default implementation of {@link SessionStorageManager}.
  */
 public class SessionStorageManagerImpl implements SessionStorageManager {
-    private static final String TAG = "SessionStorageManagerImpl";
+    private static final Log.Tag TAG = new Log.Tag("SesnStorageMgrImpl");
 
     /** Delete temporary session directory remnants after ONE day. */
     private static final int MAX_SESSION_AGE_MILLIS = 24 * 60 * 60 * 1000;
diff --git a/src/com/android/camera/settings/SettingsManager.java b/src/com/android/camera/settings/SettingsManager.java
index f4a98ca..2fd9d54 100644
--- a/src/com/android/camera/settings/SettingsManager.java
+++ b/src/com/android/camera/settings/SettingsManager.java
@@ -20,12 +20,12 @@
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.preference.PreferenceManager;
-import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.camera.ListPreference;
 import com.android.camera.app.AppController;
 import com.android.camera.app.LocationManager;
+import com.android.camera.debug.Log;
 import com.android.camera.util.CameraUtil;
 import com.android.camera.util.SettingsHelper;
 import com.android.camera2.R;
@@ -38,7 +38,7 @@
  * local SharedPreferences.
  */
 public class SettingsManager {
-    private static final String TAG = "SettingsManager";
+    private static final Log.Tag TAG = new Log.Tag("SettingsManager");
 
     private final Context mContext;
     private final SharedPreferences mDefaultSettings;
diff --git a/src/com/android/camera/settings/SettingsUtil.java b/src/com/android/camera/settings/SettingsUtil.java
index 32dbe96..93613a1 100644
--- a/src/com/android/camera/settings/SettingsUtil.java
+++ b/src/com/android/camera/settings/SettingsUtil.java
@@ -22,10 +22,10 @@
 import android.hardware.Camera.Parameters;
 import android.hardware.Camera.Size;
 import android.media.CamcorderProfile;
-import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.camera.app.CameraManager;
+import com.android.camera.debug.Log;
 import com.android.camera.settings.SettingsManager.SettingsCapabilities;
 import com.android.camera.util.Callback;
 import com.android.camera2.R;
@@ -95,7 +95,7 @@
         }
     }
 
-    private static final String TAG = "SettingsUtil";
+    private static final Log.Tag TAG = new Log.Tag("SettingsUtil");
 
     /** Enable debug output. */
     private static final boolean DEBUG = false;
@@ -140,8 +140,8 @@
     public static void setCameraPictureSize(String sizeSetting, List<Size> supported,
             Parameters parameters, int cameraId) {
         Size selectedSize = getCameraPictureSize(sizeSetting, supported, cameraId);
-        Log.d(TAG, "Selected " + sizeSetting + " resolution: " + selectedSize.width + "x"
-                + selectedSize.height);
+        Log.d(TAG, "Selected " + sizeSetting + " resolution: " + selectedSize.width + "x" +
+                selectedSize.height);
         parameters.setPictureSize(selectedSize.width, selectedSize.height);
     }
 
diff --git a/src/com/android/camera/tinyplanet/TinyPlanetFragment.java b/src/com/android/camera/tinyplanet/TinyPlanetFragment.java
index f4892aa..457ff7b 100644
--- a/src/com/android/camera/tinyplanet/TinyPlanetFragment.java
+++ b/src/com/android/camera/tinyplanet/TinyPlanetFragment.java
@@ -28,7 +28,6 @@
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
-import android.util.Log;
 import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -45,6 +44,7 @@
 import com.android.camera.app.CameraApp;
 import com.android.camera.app.MediaSaver;
 import com.android.camera.app.MediaSaver.OnMediaSavedListener;
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.tinyplanet.TinyPlanetPreview.PreviewSizeListener;
 import com.android.camera.util.XmpUtil;
@@ -83,7 +83,7 @@
             "CroppedAreaTopPixels";
     public static final String GOOGLE_PANO_NAMESPACE = "http://ns.google.com/photos/1.0/panorama/";
 
-    private static final String TAG = "TinyPlanetActivity";
+    private static final Log.Tag TAG = new Log.Tag("TinyPlanetActivity");
     /** Delay between a value update and the renderer running. */
     private static final int RENDER_DELAY_MILLIS = 50;
     /** Filename prefix to prepend to the original name for the new file. */
diff --git a/src/com/android/camera/ui/BottomBar.java b/src/com/android/camera/ui/BottomBar.java
index ebbf743..b375d5d 100644
--- a/src/com/android/camera/ui/BottomBar.java
+++ b/src/com/android/camera/ui/BottomBar.java
@@ -34,6 +34,7 @@
 import android.widget.LinearLayout;
 
 import com.android.camera.ShutterButton;
+import com.android.camera.debug.Log;
 import com.android.camera.util.Gusterpolator;
 import com.android.camera2.R;
 
@@ -72,7 +73,7 @@
         public void fitAndAlignRightInRect(RectF rect);
     }
 
-    private static final String TAG = "BottomBar";
+    private static final Log.Tag TAG = new Log.Tag("BottomBar");
 
     private static final int CIRCLE_ANIM_DURATION_MS = 300;
 
diff --git a/src/com/android/camera/ui/CaptureAnimationOverlay.java b/src/com/android/camera/ui/CaptureAnimationOverlay.java
index a6b6dea..ffad112 100644
--- a/src/com/android/camera/ui/CaptureAnimationOverlay.java
+++ b/src/com/android/camera/ui/CaptureAnimationOverlay.java
@@ -27,6 +27,7 @@
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.camera.debug.Log;
 import com.android.camera.util.Gusterpolator;
 import com.android.camera2.R;
 
@@ -36,7 +37,7 @@
  */
 public class CaptureAnimationOverlay extends View
     implements PreviewStatusListener.PreviewAreaChangedListener {
-    private final static String TAG = "CaptureAnimationOverlay";
+    private final static Log.Tag TAG = new Log.Tag("CaptureAnimOverlay");
 
     private final static int FLASH_ANIMATION_DURATION_MS = 350;
     private final static int FLASH_CIRCLE_SHRINK_DURATION_MS = 200;
diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java
index 01d9b1e..8d5c292 100644
--- a/src/com/android/camera/ui/FaceView.java
+++ b/src/com/android/camera/ui/FaceView.java
@@ -27,15 +27,15 @@
 import android.os.Handler;
 import android.os.Message;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 
+import com.android.camera.debug.Log;
 import com.android.camera.util.CameraUtil;
 import com.android.camera2.R;
 
 public class FaceView extends View
     implements FocusIndicator, Rotatable, PreviewStatusListener.PreviewAreaChangedListener {
-    private static final String TAG = "CAM FaceView";
+    private static final Log.Tag TAG = new Log.Tag("FaceView");
     private final boolean LOGV = false;
     // The value for android.hardware.Camera.setDisplayOrientation.
     private int mDisplayOrientation;
@@ -90,7 +90,9 @@
     }
 
     public void setFaces(Face[] faces) {
-        if (LOGV) Log.v(TAG, "Num of faces=" + faces.length);
+        if (LOGV) {
+            Log.v(TAG, "Num of faces=" + faces.length);
+        }
         if (mPause) return;
         if (mFaces != null) {
             if ((faces.length > 0 && mFaces.length == 0)
@@ -113,7 +115,9 @@
 
     public void setDisplayOrientation(int orientation) {
         mDisplayOrientation = orientation;
-        if (LOGV) Log.v(TAG, "mDisplayOrientation=" + orientation);
+        if (LOGV) {
+            Log.v(TAG, "mDisplayOrientation=" + orientation);
+        }
     }
 
     @Override
@@ -124,7 +128,9 @@
 
     public void setMirror(boolean mirror) {
         mMirror = mirror;
-        if (LOGV) Log.v(TAG, "mMirror=" + mirror);
+        if (LOGV) {
+            Log.v(TAG, "mMirror=" + mirror);
+        }
     }
 
     public boolean faceExists() {
@@ -197,9 +203,13 @@
 
                 // Transform the coordinates.
                 mRect.set(mFaces[i].rect);
-                if (LOGV) CameraUtil.dumpRect(mRect, "Original rect");
+                if (LOGV) {
+                    CameraUtil.dumpRect(mRect, "Original rect");
+                }
                 mMatrix.mapRect(mRect);
-                if (LOGV) CameraUtil.dumpRect(mRect, "Transformed rect");
+                if (LOGV) {
+                    CameraUtil.dumpRect(mRect, "Transformed rect");
+                }
                 mPaint.setColor(mColor);
                 mRect.offset(mPreviewArea.left, mPreviewArea.top);
                 canvas.drawOval(mRect, mPaint);
diff --git a/src/com/android/camera/ui/FilmstripGestureRecognizer.java b/src/com/android/camera/ui/FilmstripGestureRecognizer.java
index 43ea111..17e8e2f 100644
--- a/src/com/android/camera/ui/FilmstripGestureRecognizer.java
+++ b/src/com/android/camera/ui/FilmstripGestureRecognizer.java
@@ -21,11 +21,13 @@
 import android.view.MotionEvent;
 import android.view.ScaleGestureDetector;
 
+import com.android.camera.debug.Log;
+
 // This class aggregates two gesture detectors: GestureDetector,
 // ScaleGestureDetector.
 public class FilmstripGestureRecognizer {
     @SuppressWarnings("unused")
-    private static final String TAG = "FilmStripGestureRecognizer";
+    private static final Log.Tag TAG = new Log.Tag("FStripGestureRecog");
 
     public interface Listener {
         boolean onSingleTapUp(float x, float y);
diff --git a/src/com/android/camera/ui/MainActivityLayout.java b/src/com/android/camera/ui/MainActivityLayout.java
index ff0991d..d1f2f41 100644
--- a/src/com/android/camera/ui/MainActivityLayout.java
+++ b/src/com/android/camera/ui/MainActivityLayout.java
@@ -16,67 +16,28 @@
 
 package com.android.camera.ui;
 
-import android.app.Activity;
 import android.content.Context;
-import android.content.Intent;
-import android.provider.MediaStore;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.widget.FrameLayout;
 
-import com.android.camera.util.UsageStatistics;
-import com.android.camera.widget.FilmstripLayout;
-import com.android.camera2.R;
-
-import com.google.common.logging.eventprotos;
+import com.android.camera.debug.Log;
 
 public class MainActivityLayout extends FrameLayout {
 
-    // Only check for intercepting touch events within first 500ms
-    private static final int SWIPE_TIME_OUT = 500;
-
-    private ModeListView mModeList;
-    private FilmstripLayout mFilmstripLayout;
-    private boolean mCheckToIntercept;
     private MotionEvent mDown;
-    private final int mSlop;
-    private final String TAG = "MainActivityLayout";
+    private final Log.Tag TAG = new Log.Tag("MainActivityLayout");
     private boolean mRequestToInterceptTouchEvents = false;
     private View mTouchReceiver = null;
-    private final boolean mIsCaptureIntent;
-
-    // TODO: This can be removed once all modules use the new swipe logic.
-    @Deprecated
-    private boolean mSwipeEnabled = true;
 
     public MainActivityLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mSlop = ViewConfiguration.get(context).getScaledTouchSlop();
-
-        Activity activity = (Activity) context;
-        Intent intent = activity.getIntent();
-        String action = intent.getAction();
-        mIsCaptureIntent = (MediaStore.ACTION_IMAGE_CAPTURE.equals(action)
-                || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(action)
-                || MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
-    }
-
-    /**
-     * Enables or disables the swipe for modules not supporting the new swipe
-     * logic yet.
-     */
-    @Deprecated
-    public void setSwipeEnabled(boolean enabled) {
-        mSwipeEnabled = enabled;
     }
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
-            mCheckToIntercept = true;
             mDown = MotionEvent.obtain(ev);
             mTouchReceiver = null;
             mRequestToInterceptTouchEvents = false;
@@ -87,7 +48,6 @@
             return true;
         } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
             // Do not intercept touch once child is in zoom mode
-            mCheckToIntercept = false;
             return false;
         }
         return false;
@@ -102,12 +62,6 @@
         return false;
     }
 
-    @Override
-    public void onFinishInflate() {
-        mModeList = (ModeListView) findViewById(R.id.mode_list_layout);
-        mFilmstripLayout = (FilmstripLayout) findViewById(R.id.filmstrip_layout);
-    }
-
     public void redirectTouchEventsTo(View touchReceiver) {
         if (touchReceiver == null) {
             Log.e(TAG, "Cannot redirect touch to a null receiver.");
diff --git a/src/com/android/camera/ui/ModeListView.java b/src/com/android/camera/ui/ModeListView.java
index f44dd55..be45763 100644
--- a/src/com/android/camera/ui/ModeListView.java
+++ b/src/com/android/camera/ui/ModeListView.java
@@ -31,7 +31,6 @@
 import android.os.AsyncTask;
 import android.os.SystemClock;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.SparseArray;
 import android.view.GestureDetector;
 import android.view.LayoutInflater;
@@ -41,6 +40,7 @@
 import android.widget.LinearLayout;
 
 import com.android.camera.app.CameraAppUI;
+import com.android.camera.debug.Log;
 import com.android.camera.util.CameraUtil;
 import com.android.camera.util.Gusterpolator;
 import com.android.camera.widget.AnimationEffects;
@@ -61,7 +61,7 @@
         implements PreviewStatusListener.PreviewAreaChangedListener,
         ModeSelectorItem.VisibleWidthChangedListener {
 
-    private static final String TAG = "ModeListView";
+    private static final Log.Tag TAG = new Log.Tag("ModeListView");
 
     // Animation Durations
     private static final int DEFAULT_DURATION_MS = 200;
@@ -1244,8 +1244,8 @@
         if (modeSelectorIndex < mTotalModes && modeSelectorIndex >= 0) {
             return mSupportedModes.get(modeSelectorIndex);
         }
-        Log.e(TAG, "Invalid mode selector index: " + modeSelectorIndex + ", total modes: "
-                + mTotalModes);
+        Log.e(TAG, "Invalid mode selector index: " + modeSelectorIndex + ", total modes: " +
+                mTotalModes);
         return getResources().getInteger(R.integer.camera_mode_photo);
     }
 
diff --git a/src/com/android/camera/ui/ModeTransitionView.java b/src/com/android/camera/ui/ModeTransitionView.java
index e9c6841..ce73997 100644
--- a/src/com/android/camera/ui/ModeTransitionView.java
+++ b/src/com/android/camera/ui/ModeTransitionView.java
@@ -30,12 +30,12 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 import android.view.View;
 
 import com.android.camera.app.CameraAppUI;
+import com.android.camera.debug.Log;
 import com.android.camera.util.Gusterpolator;
 import com.android.camera2.R;
 
@@ -44,7 +44,7 @@
  * It should only be visible during mode switch.
  */
 public class ModeTransitionView extends View {
-    private static final String TAG = "ModeTransitionView";
+    private static final Log.Tag TAG = new Log.Tag("ModeTransView");
 
     private static final int PEEP_HOLE_ANIMATION_DURATION_MS = 300;
     private static final int ICON_FADE_OUT_DURATION_MS = 850;
diff --git a/src/com/android/camera/ui/OverlayRenderer.java b/src/com/android/camera/ui/OverlayRenderer.java
index 417e219..110e10f 100644
--- a/src/com/android/camera/ui/OverlayRenderer.java
+++ b/src/com/android/camera/ui/OverlayRenderer.java
@@ -20,9 +20,11 @@
 import android.graphics.Canvas;
 import android.view.MotionEvent;
 
+import com.android.camera.debug.Log;
+
 public abstract class OverlayRenderer implements RenderOverlay.Renderer {
 
-    private static final String TAG = "CAM OverlayRenderer";
+    private static final Log.Tag TAG = new Log.Tag("OverlayRenderer");
     protected RenderOverlay mOverlay;
 
     protected int mLeft, mTop, mRight, mBottom;
diff --git a/src/com/android/camera/ui/PieRenderer.java b/src/com/android/camera/ui/PieRenderer.java
index 880e529..935b5f6 100644
--- a/src/com/android/camera/ui/PieRenderer.java
+++ b/src/com/android/camera/ui/PieRenderer.java
@@ -36,6 +36,7 @@
 import android.view.animation.Animation;
 import android.view.animation.Transformation;
 
+import com.android.camera.debug.Log;
 import com.android.camera.drawable.TextDrawable;
 import com.android.camera2.R;
 
@@ -48,7 +49,7 @@
 public class PieRenderer extends OverlayRenderer
         implements FocusIndicator {
 
-    private static final String TAG = "PieRenderer";
+    private static final Log.Tag TAG = new Log.Tag("PieRenderer");
 
     // Sometimes continuous autofocus starts and stops several times quickly.
     // These states are used to make sure the animation is run for at least some
diff --git a/src/com/android/camera/ui/PreviewOverlay.java b/src/com/android/camera/ui/PreviewOverlay.java
index dc8e22a..2a29a64 100644
--- a/src/com/android/camera/ui/PreviewOverlay.java
+++ b/src/com/android/camera/ui/PreviewOverlay.java
@@ -28,6 +28,7 @@
 import android.view.ScaleGestureDetector;
 import android.view.View;
 
+import com.android.camera.debug.Log;
 import com.android.camera2.R;
 
 import java.util.List;
@@ -47,7 +48,7 @@
 public class PreviewOverlay extends View
     implements PreviewStatusListener.PreviewAreaChangedListener {
 
-    private static final String TAG = "PreviewOverlay";
+    private static final Log.Tag TAG = new Log.Tag("PreviewOverlay");
 
     public static final int ZOOM_MIN_FACTOR = 100;
 
@@ -232,7 +233,7 @@
      * of any change in scale, and draw the zoom UI on screen.
      */
     private class ZoomProcessor implements ScaleGestureDetector.OnScaleGestureListener {
-        private static final String TAG = "ZoomProcessor";
+        private final Log.Tag TAG = new Log.Tag("ZoomProcessor");
 
         // Diameter of Zoom UI as fraction of maximum possible without clipping.
         private static final float ZOOM_UI_SIZE = 0.8f;
diff --git a/src/com/android/camera/ui/RenderOverlay.java b/src/com/android/camera/ui/RenderOverlay.java
index e74ee46..8daf819 100644
--- a/src/com/android/camera/ui/RenderOverlay.java
+++ b/src/com/android/camera/ui/RenderOverlay.java
@@ -24,13 +24,14 @@
 import android.widget.FrameLayout;
 
 import com.android.camera.PreviewGestures;
+import com.android.camera.debug.Log;
 
 import java.util.ArrayList;
 import java.util.List;
 
 public class RenderOverlay extends FrameLayout {
 
-    private static final String TAG = "RenderOverlay";
+    private static final Log.Tag TAG = new Log.Tag("RenderOverlay");
     private PreviewGestures.SingleTapListener mTapListener;
 
     interface Renderer {
diff --git a/src/com/android/camera/ui/RotatableLayout.java b/src/com/android/camera/ui/RotatableLayout.java
index 6867e6a..85948c6 100644
--- a/src/com/android/camera/ui/RotatableLayout.java
+++ b/src/com/android/camera/ui/RotatableLayout.java
@@ -25,6 +25,7 @@
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import com.android.camera.debug.Log;
 import com.android.camera.util.CameraUtil;
 
 /* RotatableLayout rotates itself as well as all its children when orientation
@@ -37,7 +38,7 @@
 
 public class RotatableLayout extends FrameLayout {
 
-    private static final String TAG = "RotatableLayout";
+    private static final Log.Tag TAG = new Log.Tag("RotatableLayout");
     private static final int UNKOWN_ORIENTATION = -1;
     // Initial orientation of the layout (ORIENTATION_PORTRAIT, or ORIENTATION_LANDSCAPE)
     private int mInitialOrientation;
@@ -280,4 +281,4 @@
         rotateClockwise(view);
         rotateClockwise(view);
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/camera/ui/RotateImageView.java b/src/com/android/camera/ui/RotateImageView.java
index 05e1a7c..457b474 100644
--- a/src/com/android/camera/ui/RotateImageView.java
+++ b/src/com/android/camera/ui/RotateImageView.java
@@ -29,13 +29,15 @@
 import android.view.animation.AnimationUtils;
 import android.widget.ImageView;
 
+import com.android.camera.debug.Log;
+
 /**
  * A @{code ImageView} which can rotate it's content.
  */
 public class RotateImageView extends TwoStateImageView implements Rotatable {
 
     @SuppressWarnings("unused")
-    private static final String TAG = "RotateImageView";
+    private static final Log.Tag TAG = new Log.Tag("RotateImageView");
 
     private static final int ANIMATION_SPEED = 270; // 270 deg/sec
 
diff --git a/src/com/android/camera/ui/RotateLayout.java b/src/com/android/camera/ui/RotateLayout.java
index 8539eb6..0110d9c 100644
--- a/src/com/android/camera/ui/RotateLayout.java
+++ b/src/com/android/camera/ui/RotateLayout.java
@@ -22,11 +22,13 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.camera.debug.Log;
+
 // A RotateLayout is designed to display a single item and provides the
 // capabilities to rotate the item.
 public class RotateLayout extends ViewGroup implements Rotatable {
     @SuppressWarnings("unused")
-    private static final String TAG = "RotateLayout";
+    private static final Log.Tag TAG = new Log.Tag("RotateLayout");
     private int mOrientation;
     private Matrix mMatrix = new Matrix();
     protected View mChild;
diff --git a/src/com/android/camera/ui/ZoomRenderer.java b/src/com/android/camera/ui/ZoomRenderer.java
index 39bae08..2b997b2 100644
--- a/src/com/android/camera/ui/ZoomRenderer.java
+++ b/src/com/android/camera/ui/ZoomRenderer.java
@@ -23,6 +23,7 @@
 import android.graphics.Paint;
 import android.view.ScaleGestureDetector;
 
+import com.android.camera.debug.Log;
 import com.android.camera2.R;
 
 // TODO: remove this; functionality has been moved to PreviewOverlay.
@@ -30,7 +31,7 @@
 public class ZoomRenderer extends OverlayRenderer
         implements ScaleGestureDetector.OnScaleGestureListener {
 
-    private static final String TAG = "ZoomRenderer";
+    private static final Log.Tag TAG = new Log.Tag("ZoomRenderer");
 
     final private int mMinIndex = 0;
     private int mMaxIndex;
diff --git a/src/com/android/camera/ui/ZoomView.java b/src/com/android/camera/ui/ZoomView.java
index 1e2add0..252838d 100644
--- a/src/com/android/camera/ui/ZoomView.java
+++ b/src/com/android/camera/ui/ZoomView.java
@@ -26,10 +26,11 @@
 import android.graphics.RectF;
 import android.net.Uri;
 import android.os.AsyncTask;
-import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
+
 import com.android.camera.data.LocalDataUtil;
+import com.android.camera.debug.Log;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -37,7 +38,7 @@
 
 public class ZoomView extends ImageView {
 
-    private static final String TAG = "ZoomView";
+    private static final Log.Tag TAG = new Log.Tag("ZoomView");
 
     private int mViewportWidth = 0;
     private int mViewportHeight = 0;
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index 7181209..3a51d29 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -42,7 +42,6 @@
 import android.telephony.TelephonyManager;
 import android.util.DisplayMetrics;
 import android.util.FloatMath;
-import android.util.Log;
 import android.util.TypedValue;
 import android.view.Display;
 import android.view.OrientationEventListener;
@@ -55,6 +54,7 @@
 
 import com.android.camera.CameraActivity;
 import com.android.camera.CameraDisabledException;
+import com.android.camera.debug.Log;
 import com.android.camera.filmstrip.ImageData;
 import com.android.camera2.R;
 
@@ -71,7 +71,7 @@
  * Collection of utility functions used in this package.
  */
 public class CameraUtil {
-    private static final String TAG = "Util";
+    private static final Log.Tag TAG = new Log.Tag("Util");
 
     // For calculate the best fps range for still image capture.
     private final static int MAX_PREVIEW_FPS_TIMES_1000 = 400000;
diff --git a/src/com/android/camera/util/ImageLoader.java b/src/com/android/camera/util/ImageLoader.java
index a058924..3040e0e 100644
--- a/src/com/android/camera/util/ImageLoader.java
+++ b/src/com/android/camera/util/ImageLoader.java
@@ -27,9 +27,9 @@
 import android.graphics.Rect;
 import android.net.Uri;
 import android.provider.MediaStore;
-import android.util.Log;
 import android.webkit.MimeTypeMap;
 
+import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.exif.ExifTag;
 
@@ -41,7 +41,7 @@
 
 public final class ImageLoader {
 
-    private static final String TAG = "ImageLoader";
+    private static final Log.Tag TAG = new Log.Tag("ImageLoader");
 
     public static final String JPEG_MIME_TYPE = "image/jpeg";
     public static final int DEFAULT_COMPRESS_QUALITY = 95;
diff --git a/src/com/android/camera/util/IntentHelper.java b/src/com/android/camera/util/IntentHelper.java
index 66fbf84..4baa466 100644
--- a/src/com/android/camera/util/IntentHelper.java
+++ b/src/com/android/camera/util/IntentHelper.java
@@ -21,11 +21,13 @@
 import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.util.Log;
+
+import com.android.camera.debug.Log;
 
 import java.util.List;
 
 public class IntentHelper {
+    private static final Log.Tag TAG = new Log.Tag("IntentHelper");
 
     public static Intent getDefaultGalleryIntent(Context context) {
         PackageManager pm = context.getPackageManager();
@@ -46,7 +48,7 @@
                     firstPackage.activityInfo.name);
         }
         for (ResolveInfo info : resolveInfos) {
-            Log.v("intent helper", info.resolvePackageName + ':' + info.activityInfo.packageName +
+            Log.v(TAG, info.resolvePackageName + ':' + info.activityInfo.packageName +
                     ":" + info.activityInfo.name + ',' + info.activityInfo.enabled);
         }
         return intent;
diff --git a/src/com/android/camera/util/XmpUtil.java b/src/com/android/camera/util/XmpUtil.java
index c985a6b..b39bc27 100644
--- a/src/com/android/camera/util/XmpUtil.java
+++ b/src/com/android/camera/util/XmpUtil.java
@@ -16,12 +16,11 @@
 
 package com.android.camera.util;
 
-import android.util.Log;
-
 import com.adobe.xmp.XMPException;
 import com.adobe.xmp.XMPMeta;
 import com.adobe.xmp.XMPMetaFactory;
 import com.adobe.xmp.options.SerializeOptions;
+import com.android.camera.debug.Log;
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -47,7 +46,7 @@
  * XmpUtil.writeXMPMeta(filename, xmpMeta);
  */
 public class XmpUtil {
-  private static final String TAG = "XmpUtil";
+  private static final Log.Tag TAG = new Log.Tag("XmpUtil");
   private static final int XMP_HEADER_SIZE = 29;
   private static final String XMP_HEADER = "http://ns.adobe.com/xap/1.0/\0";
   private static final int MAX_XMP_BUFFER_SIZE = 65502;
diff --git a/src/com/android/camera/widget/FilmstripView.java b/src/com/android/camera/widget/FilmstripView.java
index c49a813..fb84777 100644
--- a/src/com/android/camera/widget/FilmstripView.java
+++ b/src/com/android/camera/widget/FilmstripView.java
@@ -30,7 +30,6 @@
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.util.SparseArray;
 import android.view.MotionEvent;
 import android.view.View;
@@ -39,6 +38,7 @@
 import android.widget.Scroller;
 
 import com.android.camera.CameraActivity;
+import com.android.camera.debug.Log;
 import com.android.camera.filmstrip.DataAdapter;
 import com.android.camera.filmstrip.FilmstripController;
 import com.android.camera.filmstrip.ImageData;
@@ -54,7 +54,7 @@
 import java.util.Queue;
 
 public class FilmstripView extends ViewGroup {
-    private static final String TAG = "FilmStripView";
+    private static final Log.Tag TAG = new Log.Tag("FilmstripView");
 
     private static final int BUFFER_SIZE = 5;
     private static final int GEOMETRY_ADJUST_TIME_MS = 400;
diff --git a/src/com/android/camera/widget/IndicatorIconController.java b/src/com/android/camera/widget/IndicatorIconController.java
index 216fc11..e226ccd 100644
--- a/src/com/android/camera/widget/IndicatorIconController.java
+++ b/src/com/android/camera/widget/IndicatorIconController.java
@@ -19,18 +19,14 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.ImageView;
 
 import com.android.camera.ButtonManager;
 import com.android.camera.app.AppController;
-import com.android.camera.module.ModulesInfo;
+import com.android.camera.debug.Log;
 import com.android.camera.settings.SettingsManager;
 import com.android.camera.util.PhotoSphereHelper;
-
 import com.android.camera2.R;
 
 /**
@@ -44,7 +40,7 @@
     implements SettingsManager.OnSettingChangedListener,
                ButtonManager.ButtonStatusListener {
 
-    private final static String TAG = "IndicatorIconController";
+    private final static Log.Tag TAG = new Log.Tag("IndicatorIconCtrlr");
 
     private ImageView mFlashIndicator;
     private ImageView mHdrIndicator;
diff --git a/src/com/android/camera/widget/ModeOptionsOverlay.java b/src/com/android/camera/widget/ModeOptionsOverlay.java
index 3cd4591..278bb16 100644
--- a/src/com/android/camera/widget/ModeOptionsOverlay.java
+++ b/src/com/android/camera/widget/ModeOptionsOverlay.java
@@ -30,9 +30,9 @@
 import android.widget.LinearLayout;
 
 import com.android.camera.ShutterButton;
+import com.android.camera.debug.Log;
 import com.android.camera.ui.PreviewOverlay;
 import com.android.camera.ui.PreviewStatusListener;
-
 import com.android.camera2.R;
 
 /**
@@ -45,7 +45,7 @@
                IndicatorIconController.OnIndicatorVisibilityChangedListener,
                ShutterButton.OnShutterButtonListener {
 
-    private final static String TAG = "ModeOptionsOverlay";
+    private final static Log.Tag TAG = new Log.Tag("ModeOptionsOverlay");
 
     private static final int BOTTOMBAR_OPTIONS_TIMEOUT_MS = 2000;
     private final static int BOTTOM_RIGHT = Gravity.BOTTOM | Gravity.RIGHT;
diff --git a/src/com/android/camera/widget/Preloader.java b/src/com/android/camera/widget/Preloader.java
index 75b9eab..cb196a3 100644
--- a/src/com/android/camera/widget/Preloader.java
+++ b/src/com/android/camera/widget/Preloader.java
@@ -1,8 +1,9 @@
 package com.android.camera.widget;
 
-import android.util.Log;
 import android.widget.AbsListView;
 
+import com.android.camera.debug.Log;
+
 import java.util.Collections;
 import java.util.List;
 import java.util.Queue;
@@ -16,7 +17,7 @@
  *           preloads.
  */
 public class Preloader<T, Y> implements AbsListView.OnScrollListener {
-    private static final String TAG = "Preloader";
+    private static final Log.Tag TAG = new Log.Tag("Preloader");
 
     /**
      * Implemented by the source for items that should be preloaded.
@@ -94,10 +95,8 @@
             end = Math.min(first, mLastStart);
         }
 
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "preload first=" + first + " increasing=" + increasing + " start=" + start
-                    + " end=" + end);
-        }
+        Log.v(TAG, "preload first=" + first + " increasing=" + increasing + " start=" + start +
+                " end=" + end);
 
         mLastEnd = end;
         mLastStart = start;