<commit_before>/*
 * Copyright 2017, <NAME>
 *
 * 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.fkeglevich.rawdumper.camera.async.pipeline.picture;

import android.hardware.Camera;
import android.os.Handler;
import android.os.Looper;

import com.fkeglevich.rawdumper.async.operation.AsyncOperation;
import com.fkeglevich.rawdumper.camera.action.listener.PictureExceptionListener;
import com.fkeglevich.rawdumper.camera.action.listener.PictureListener;
import com.fkeglevich.rawdumper.camera.async.CameraContext;
import com.fkeglevich.rawdumper.camera.async.direct.RestartableCamera;
import com.fkeglevich.rawdumper.camera.extension.ICameraExtension;
import com.fkeglevich.rawdumper.camera.extension.RawImageCallbackAccess;
import com.fkeglevich.rawdumper.io.Directories;
import com.fkeglevich.rawdumper.io.async.IOThread;
import com.fkeglevich.rawdumper.raw.capture.CaptureInfo;
import com.fkeglevich.rawdumper.raw.capture.builder.ACaptureInfoBuilder;
import com.fkeglevich.rawdumper.raw.capture.builder.FromI3av4FileBuilder;
import com.fkeglevich.rawdumper.su.ShellManager;
import com.fkeglevich.rawdumper.util.Mutable;
import com.fkeglevich.rawdumper.util.Nothing;
import com.fkeglevich.rawdumper.util.ThreadUtil;
import com.fkeglevich.rawdumper.util.exception.MessageException;

import java.io.File;
import java.io.IOException;

import eu.chainfire.libsuperuser.Shell;

/**
 * TODO: Add class header
 * <p>
 * Created by <NAME> on 05/11/17.
 */

public class RetryingRawPipeline implements PicturePipeline
{
    private final Mutable<ICameraExtension> cameraExtension;
    private final Object                    lock;
    private final CameraContext             cameraContext;
    private final RestartableCamera         restartableCamera;
    private final Handler                   uiHandler;

    private Camera.Parameters               parameters = null;
    private boolean                         ignoreError = false;

    private final Camera.ErrorCallback      errorCallback = new Camera.ErrorCallback()
    {
        @Override
        public void onError(int error, Camera camera)
        {
            if (ignoreError)
            {
                ThreadUtil.simpleDelay(2000);
                ignoreError = false;
                String dumpDirectory = cameraContext.getDeviceInfo().getDumpDirectoryLocation();
                String partialPath = Directories.getPartialPicturesDirectory().getAbsolutePath();
                ShellManager.getInstance().addSingleCommand("mv " + dumpDirectory + "/*.i3av4" + " " + partialPath, new Shell.OnCommandLineListener()
                {
                    @Override
                    public void onCommandResult(int commandCode, int exitCode)
                    {
                        processPicture();
                    }

                    @Override
                    public void onLine(String line)
                    {

                    }
                });
            }
        }
    };
    private PictureListener nextPictureCallback;
    private PictureExceptionListener nextExceptionCallback;

    RetryingRawPipeline(Mutable<ICameraExtension> cameraExtension, Object lock, CameraContext cameraContext, RestartableCamera restartableCamera)
    {
        this.cameraExtension    = cameraExtension;
        this.lock               = lock;
        this.cameraContext      = cameraContext;
        this.restartableCamera  = restartableCamera;
        this.uiHandler = new Handler(Looper.getMainLooper());
    }

    @Override
    public void takePicture(PictureListener pictureCallback, PictureExceptionListener exceptionCallback)
    {
        synchronized (lock)
        {
            nextPictureCallback = pictureCallback;
            nextExceptionCallback = exceptionCallback;
            Camera camera = cameraExtension.get().getCameraDevice();
            parameters = camera.getParameters();
            ignoreError = true;
            camera.setErrorCallback(errorCallback);
            camera.takePicture(null, null, null);
        }
    }

    private void processPicture()
    {
        File i3av4File = Directories.getPartialPicturesDirectory().listFiles()[0];
        ACaptureInfoBuilder captureInfoBuilder = new FromI3av4FileBuilder(cameraContext, i3av4File, parameters);
        CaptureInfo captureInfo = captureInfoBuilder.build();

        IOThread.getIOAccess().saveDng(captureInfo, new AsyncOperation<Nothing>()
        {
            @Override
            protected void execute(Nothing argument)
            {
                nextPictureCallback.onPictureSaved();
            }
        }, new AsyncOperation<MessageException>()
        {
            @Override
            protected void execute(MessageException argument)
            {
                nextExceptionCallback.onException(argument);
            }
        });

        try
        {
            restartableCamera.restartCamera();
        } catch (MessageException e)
        {
            e.printStackTrace();
        } catch (IOException e)
        {
            e.printStackTrace();
        }

        uiHandler.post(new Runnable()
        {
            @Override
            public void run()
            {
                nextPictureCallback.onPictureTaken();
            }
        });
    }
}<commit_msg>Full-working retrying raw pipeline<commit_after>/*
 * Copyright 2017, <NAME>
 *
 * 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.fkeglevich.rawdumper.camera.async.pipeline.picture;

import android.hardware.Camera;

import com.fkeglevich.rawdumper.async.operation.AsyncOperation;
import com.fkeglevich.rawdumper.camera.action.listener.PictureExceptionListener;
import com.fkeglevich.rawdumper.camera.action.listener.PictureListener;
import com.fkeglevich.rawdumper.camera.async.CameraContext;
import com.fkeglevich.rawdumper.camera.async.CameraThread;
import com.fkeglevich.rawdumper.camera.async.direct.RestartableCamera;
import com.fkeglevich.rawdumper.camera.async.pipeline.picture.dummy.RetryingPipelineSimulator;
import com.fkeglevich.rawdumper.camera.extension.ICameraExtension;
import com.fkeglevich.rawdumper.debug.DebugFlags;
import com.fkeglevich.rawdumper.io.Directories;
import com.fkeglevich.rawdumper.io.async.IOThread;
import com.fkeglevich.rawdumper.io.async.exception.SaveFileException;
import com.fkeglevich.rawdumper.raw.capture.CaptureInfo;
import com.fkeglevich.rawdumper.raw.capture.builder.ACaptureInfoBuilder;
import com.fkeglevich.rawdumper.raw.capture.builder.FromI3av4FileBuilder;
import com.fkeglevich.rawdumper.su.ShellManager;
import com.fkeglevich.rawdumper.util.Mutable;
import com.fkeglevich.rawdumper.util.Nothing;
import com.fkeglevich.rawdumper.util.ThreadUtil;
import com.fkeglevich.rawdumper.util.exception.MessageException;

import java.io.File;

import eu.chainfire.libsuperuser.Shell;

/**
 * TODO: Add class header
 * <p>
 * Created by <NAME> on 05/11/17.
 */

public class RetryingRawPipeline implements PicturePipeline
{
    private final Mutable<ICameraExtension> cameraExtension;
    private final Object                    lock;
    private final CameraContext             cameraContext;
    private final RestartableCamera         restartableCamera;

    private Camera.Parameters               parameters = null;
    private boolean                         ignoreError = false;

    private final Camera.ErrorCallback      errorCallback = new Camera.ErrorCallback()
    {
        @Override
        public void onError(int error, Camera camera)
        {
            if (ignoreError)
            {
                ThreadUtil.simpleDelay(2000);
                restartCamera();
                ignoreError = false;
            }
        }
    };

    private final Camera.PictureCallback dummyJpegCallback = new Camera.PictureCallback()
    {
        @Override
        public void onPictureTaken(byte[] data, Camera camera)
        {
            cameraExtension.get().getCameraDevice().startPreview();
            errorCallback.onError(0, camera);
        }
    };

    private PictureListener nextPictureCallback;
    private PictureExceptionListener nextExceptionCallback;

    RetryingRawPipeline(Mutable<ICameraExtension> cameraExtension, Object lock, CameraContext cameraContext, RestartableCamera restartableCamera)
    {
        this.cameraExtension    = cameraExtension;
        this.lock               = lock;
        this.cameraContext      = cameraContext;
        this.restartableCamera  = restartableCamera;
    }

    @Override
    public void takePicture(PictureListener pictureCallback, PictureExceptionListener exceptionCallback)
    {
        synchronized (lock)
        {
            nextPictureCallback = pictureCallback;
            nextExceptionCallback = exceptionCallback;
            ignoreError = true;
            Camera camera = cameraExtension.get().getCameraDevice();
            parameters = camera.getParameters();

            if (DebugFlags.isUseRetryingPipelineSimulator())
                RetryingPipelineSimulator.simulate(cameraContext, errorCallback);
            else
            {
                camera.setErrorCallback(errorCallback);
                camera.takePicture(null, null, dummyJpegCallback);
            }
        }
    }

    private void movePictures()
    {
        String dumpDirectory = cameraContext.getDeviceInfo().getDumpDirectoryLocation();
        String partialPath = Directories.getPartialPicturesDirectory().getAbsolutePath();
        ShellManager.getInstance().addSingleCommand("mv " + dumpDirectory + "/*.i3av4" + " " + partialPath, new Shell.OnCommandLineListener()
        {
            @Override
            public void onCommandResult(int commandCode, int exitCode)
            {
                processPicture();
            }

            @Override
            public void onLine(String line)
            {   }
        });
    }

    private void processPicture()
    {
        File[] files = Directories.getPartialPicturesDirectory().listFiles();
        if (files.length != 1)
        {
            nextExceptionCallback.onException(new SaveFileException());
            return;
        }

        File i3av4File = files[0];
        ACaptureInfoBuilder captureInfoBuilder = new FromI3av4FileBuilder(cameraContext, i3av4File, parameters);
        CaptureInfo captureInfo = captureInfoBuilder.build();

        IOThread.getIOAccess().saveDng(captureInfo, new AsyncOperation<Nothing>()
        {
            @Override
            protected void execute(Nothing argument)
            {
                nextPictureCallback.onPictureSaved();
            }
        }, new AsyncOperation<MessageException>()
        {
            @Override
            protected void execute(MessageException argument)
            {
                nextExceptionCallback.onException(argument);
            }
        });
    }

    private void restartCamera()
    {
        CameraThread.getInstance().restartCamera(restartableCamera, new AsyncOperation<Nothing>()
        {
            @Override
            protected void execute(Nothing argument)
            {
                movePictures();
                nextPictureCallback.onPictureTaken();
            }
        }, new AsyncOperation<MessageException>()
        {
            @Override
            protected void execute(MessageException argument)
            {
                nextExceptionCallback.onException(argument);
            }
        });
    }


}
{'fraction_non_alphanumeric': 0.08004183090660445, 'fraction_numerical': 0.004826643069744992, 'mean_word_length': 2.5098814229249014, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '685072', 'n_tokens_mistral': 3254, 'n_tokens_neox': 3145, 'n_words': 662}