Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 24d6ec7b authored by nicolasroard's avatar nicolasroard
Browse files

Add background processing service

bug:7298624

Change-Id: Ie79f88fd84fdf8f4dab6a8071f06a819e247b357
parent dda606af
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -219,6 +219,11 @@
            android:grantUriPermissions="true"
            android:readPermission="com.android.gallery3d.filtershow.permission.READ"
            android:writePermission="com.android.gallery3d.filtershow.permission.WRITE" />

        <service
                android:name=".filtershow.pipeline.ProcessingService"
                android:exported="false" />

        <activity
            android:name="com.android.gallery3d.filtershow.FilterShowActivity"
            android:label="@string/title_activity_filter_show"
+5 −0
Original line number Diff line number Diff line
@@ -199,4 +199,9 @@
    <!--  Name used to indicate the final image in the state panel [CHAR LIMIT=20] -->
    <string name="state_panel_result">Result</string>

    <!-- Label for the notification [CHAR LIMIT=50] -->
    <string name="filtershow_notification_label">Saving Image</string>
    <!-- Label for the notification message [CHAR LIMIT=50] -->
    <string name="filtershow_notification_message">Processing...</string>

</resources>
+2 −2
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.BitmapUtils;
import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.filtershow.tools.SaveCopyTask;
import com.android.gallery3d.filtershow.tools.SaveImage;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.ThreadPool.Job;
import com.android.gallery3d.util.ThreadPool.JobContext;
@@ -270,7 +270,7 @@ public class LocalImage extends LocalMediaItem {
        GalleryUtils.assertNotInRenderThread();
        Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI;
        ContentResolver contentResolver = mApplication.getContentResolver();
        SaveCopyTask.deleteAuxFiles(contentResolver, getContentUri());
        SaveImage.deleteAuxFiles(contentResolver, getContentUri());
        contentResolver.delete(baseUri, "_id=?",
                new String[]{String.valueOf(id)});
    }
+97 −118
Original line number Diff line number Diff line
@@ -19,28 +19,29 @@ package com.android.gallery3d.filtershow;
import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -55,20 +56,19 @@ import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
import android.widget.Toast;

import com.android.gallery3d.R;
import com.android.gallery3d.app.PhotoPage;
import com.android.gallery3d.data.LocalAlbum;
import com.android.gallery3d.filtershow.pipeline.CachingPipeline;
import com.android.gallery3d.filtershow.pipeline.FilteringPipeline;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.category.Action;
import com.android.gallery3d.filtershow.category.CategoryAdapter;
import com.android.gallery3d.filtershow.category.CategoryView;
import com.android.gallery3d.filtershow.category.MainPanel;
import com.android.gallery3d.filtershow.editors.BasicEditor;
import com.android.gallery3d.filtershow.editors.Editor;
import com.android.gallery3d.filtershow.editors.EditorCrop;
import com.android.gallery3d.filtershow.editors.EditorDraw;
import com.android.gallery3d.filtershow.editors.EditorFlip;
import com.android.gallery3d.filtershow.editors.EditorInfo;
import com.android.gallery3d.filtershow.editors.EditorManager;
import com.android.gallery3d.filtershow.editors.EditorPanel;
import com.android.gallery3d.filtershow.editors.EditorRedEye;
@@ -76,8 +76,6 @@ import com.android.gallery3d.filtershow.editors.EditorRotate;
import com.android.gallery3d.filtershow.editors.EditorStraighten;
import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
import com.android.gallery3d.filtershow.filters.FilterFxRepresentation;
import com.android.gallery3d.filtershow.filters.FilterImageBorderRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.filters.ImageFilter;
@@ -88,9 +86,10 @@ import com.android.gallery3d.filtershow.imageshow.ImageCrop;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
import com.android.gallery3d.filtershow.pipeline.ImagePreset;
import com.android.gallery3d.filtershow.pipeline.ProcessingService;
import com.android.gallery3d.filtershow.provider.SharedImageProvider;
import com.android.gallery3d.filtershow.state.StateAdapter;
import com.android.gallery3d.filtershow.tools.SaveCopyTask;
import com.android.gallery3d.filtershow.tools.SaveImage;
import com.android.gallery3d.filtershow.tools.XmpPresets;
import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults;
import com.android.gallery3d.filtershow.ui.FramedTextButton;
@@ -101,6 +100,7 @@ import com.android.photos.data.GalleryBitmapPool;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Vector;

public class FilterShowActivity extends FragmentActivity implements OnItemClickListener,
@@ -149,6 +149,75 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    private CategoryAdapter mCategoryFiltersAdapter = null;
    private int mCurrentPanel = MainPanel.LOOKS;

    private ProcessingService mBoundService;
    private boolean mIsBound = false;

    public ProcessingService getProcessingService() {
        return mBoundService;
    }

    public boolean isSimpleEditAction() {
        return !PhotoPage.ACTION_NEXTGEN_EDIT.equalsIgnoreCase(mAction);
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            /*
             * This is called when the connection with the service has been
             * established, giving us the service object we can use to
             * interact with the service.  Because we have bound to a explicit
             * service that we know is running in our own process, we can
             * cast its IBinder to a concrete class and directly access it.
             */
            mBoundService = ((ProcessingService.LocalBinder)service).getService();
            mBoundService.setFiltershowActivity(FilterShowActivity.this);
            mBoundService.onStart();
        }

        public void onServiceDisconnected(ComponentName className) {
            /*
             * This is called when the connection with the service has been
             * unexpectedly disconnected -- that is, its process crashed.
             * Because it is running in our same process, we should never
             * see this happen.
             */
            mBoundService = null;
        }
    };

    void doBindService() {
        /*
         * Establish a connection with the service.  We use an explicit
         * class name because we want a specific service implementation that
         * we know will be running in our own process (and thus won't be
         * supporting component replacement by other applications).
         */
        bindService(new Intent(FilterShowActivity.this, ProcessingService.class),
                mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }

    void doUnbindService() {
        if (mIsBound) {
            // Detach our existing connection.
            unbindService(mConnection);
            mIsBound = false;
        }
    }

    private void setupPipeline() {
        doBindService();
        ImageFilter.setActivityForMemoryToasts(this);
    }

    public void updateUIAfterServiceStarted() {
        fillCategories();
        loadMainPanel();
        setDefaultPreset();
        extractXMPData();
        processIntent();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
@@ -160,19 +229,13 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        MasterImage.setMaster(mMasterImage);

        clearGalleryBitmapPool();
        setupPipeline();

        CachingPipeline.createRenderscriptContext(this);
        setupMasterImage();
        setDefaultValues();
        fillEditors();

        loadXML();
        loadMainPanel();

        setDefaultPreset();

        extractXMPData();
        processIntent();
        UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_EDITOR, "Main");
        UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
                UsageStatistics.CATEGORY_LIFECYCLE, UsageStatistics.LIFECYCLE_START);
@@ -251,26 +314,25 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        setupEditors();

        mEditorPlaceHolder.hide();

        mImageShow.bindAsImageLoadListener();

        fillFx();
        fillBorders();
        fillGeometry();
        fillFilters();

        setupStatePanel();
    }

    public void fillCategories() {
        fillLooks();
        fillBorders();
        fillTools();
        fillEffects();
    }

    public void setupStatePanel() {
        MasterImage.getImage().setHistoryManager(mMasterImage.getHistory());
    }

    private void fillFilters() {
        Vector<FilterRepresentation> filtersRepresentations = new Vector<FilterRepresentation>();
    private void fillEffects() {
        FiltersManager filtersManager = FiltersManager.getManager();
        filtersManager.addEffects(filtersRepresentations);

        ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getEffects();
        mCategoryFiltersAdapter = new CategoryAdapter(this);
        for (FilterRepresentation representation : filtersRepresentations) {
            if (representation.getTextId() != 0) {
@@ -280,28 +342,9 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        }
    }

    private void fillGeometry() {
        Vector<FilterRepresentation> filtersRepresentations = new Vector<FilterRepresentation>();
    private void fillTools() {
        FiltersManager filtersManager = FiltersManager.getManager();

        GeometryMetadata geo = new GeometryMetadata();
        int[] editorsId = geo.getEditorIds();
        for (int i = 0; i < editorsId.length; i++) {
            int editorId = editorsId[i];
            GeometryMetadata geometry = new GeometryMetadata(geo);
            geometry.setEditorId(editorId);
            EditorInfo editorInfo = (EditorInfo) mEditorPlaceHolder.getEditor(editorId);
            geometry.setTextId(editorInfo.getTextId());
            geometry.setOverlayId(editorInfo.getOverlayId());
            geometry.setOverlayOnly(editorInfo.getOverlayOnly());
            if (geometry.getTextId() != 0) {
                geometry.setName(getString(geometry.getTextId()));
            }
            filtersRepresentations.add(geometry);
        }

        filtersManager.addTools(filtersRepresentations);

        ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getTools();
        mCategoryGeometryAdapter = new CategoryAdapter(this);
        for (FilterRepresentation representation : filtersRepresentations) {
            mCategoryGeometryAdapter.add(new Action(this, representation));
@@ -331,7 +374,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer));
        EditorManager.addEditors(mEditorPlaceHolder);
        mEditorPlaceHolder.setOldViews(mImageViews);

    }

    private void fillEditors() {
@@ -347,10 +389,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    }

    private void setDefaultValues() {
        ImageFilter.setActivityForMemoryToasts(this);

        Resources res = getResources();
        FiltersManager.setResources(res);

        // TODO: get those values from XML.
        FramedTextButton.setTextSize((int) getPixelsFromDip(14));
@@ -379,16 +418,11 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    }

    private void fillBorders() {
        Vector<FilterRepresentation> borders = new Vector<FilterRepresentation>();

        // The "no border" implementation
        borders.add(new FilterImageBorderRepresentation(0));

        // Google-build borders
        FiltersManager.getManager().addBorders(this, borders);
        FiltersManager filtersManager = FiltersManager.getManager();
        ArrayList<FilterRepresentation> borders = filtersManager.getBorders();

        for (int i = 0; i < borders.size(); i++) {
            FilterRepresentation filter = borders.elementAt(i);
            FilterRepresentation filter = borders.get(i);
            filter.setName(getString(R.string.borders));
            if (i == 0) {
                filter.setName(getString(R.string.none));
@@ -628,16 +662,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        if (mLoadBitmapTask != null) {
            mLoadBitmapTask.cancel(false);
        }
        // TODO:  refactor, don't use so many singletons.
        FilteringPipeline.getPipeline().turnOnPipeline(false);
        MasterImage.reset();
        FilteringPipeline.reset();
        ImageFilter.resetStatics();
        FiltersManager.getPreviewManager().freeRSFilterScripts();
        FiltersManager.getManager().freeRSFilterScripts();
        FiltersManager.getHighresManager().freeRSFilterScripts();
        FiltersManager.reset();
        CachingPipeline.destroyRenderScriptContext();
        doUnbindService();
        super.onDestroy();
    }

@@ -713,7 +738,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setType(SharedImageProvider.MIME_TYPE);
        mSharedOutputFile = SaveCopyTask.getNewFile(this, MasterImage.getImage().getUri());
        mSharedOutputFile = SaveImage.getNewFile(this, MasterImage.getImage().getUri());
        Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
                Uri.encode(mSharedOutputFile.getAbsolutePath()));
        intent.putExtra(Intent.EXTRA_STREAM, uri);
@@ -744,7 +769,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    @Override
    public void onPause() {
        super.onPause();
        rsPause();
        if (mShareActionProvider != null) {
            mShareActionProvider.setOnShareTargetSelectedListener(null);
        }
@@ -753,48 +777,11 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    @Override
    public void onResume() {
        super.onResume();
        rsResume();
        if (mShareActionProvider != null) {
            mShareActionProvider.setOnShareTargetSelectedListener(this);
        }
    }

    private void rsResume() {
        ImageFilter.setActivityForMemoryToasts(this);
        MasterImage.setMaster(mMasterImage);
        if (CachingPipeline.getRenderScriptContext() == null) {
            CachingPipeline.createRenderscriptContext(this);
        }
        FiltersManager.setResources(getResources());
        if (!mLoading) {
            Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge();
            FilteringPipeline pipeline = FilteringPipeline.getPipeline();
            pipeline.setOriginal(largeBitmap);
            float previewScale = (float) largeBitmap.getWidth() /
                    (float) MasterImage.getImage().getOriginalBounds().width();
            pipeline.setPreviewScaleFactor(previewScale);
            Bitmap highresBitmap = MasterImage.getImage().getOriginalBitmapHighres();
            if (highresBitmap != null) {
                float highResPreviewScale = (float) highresBitmap.getWidth() /
                        (float) MasterImage.getImage().getOriginalBounds().width();
                pipeline.setHighResPreviewScaleFactor(highResPreviewScale);
            }
            pipeline.turnOnPipeline(true);
            MasterImage.getImage().setOriginalGeometry(largeBitmap);
        }
    }

    private void rsPause() {
        FilteringPipeline.getPipeline().turnOnPipeline(false);
        FilteringPipeline.reset();
        ImageFilter.resetStatics();
        FiltersManager.getPreviewManager().freeRSFilterScripts();
        FiltersManager.getManager().freeRSFilterScripts();
        FiltersManager.getHighresManager().freeRSFilterScripts();
        FiltersManager.reset();
        CachingPipeline.destroyRenderScriptContext();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
@@ -844,16 +831,13 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        }
    }

    private void fillFx() {
        FilterFxRepresentation nullFx =
                new FilterFxRepresentation(getString(R.string.none), 0, R.string.none);
        Vector<FilterRepresentation> filtersRepresentations = new Vector<FilterRepresentation>();
        FiltersManager.getManager().addLooks(this, filtersRepresentations);
    private void fillLooks() {
        FiltersManager filtersManager = FiltersManager.getManager();
        ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getLooks();

        mCategoryLooksAdapter = new CategoryAdapter(this);
        int verticalItemHeight = (int) getResources().getDimension(R.dimen.action_item_height);
        mCategoryLooksAdapter.setItemHeight(verticalItemHeight);
        mCategoryLooksAdapter.add(new Action(this, nullFx, Action.FULL_VIEW));
        for (FilterRepresentation representation : filtersRepresentations) {
            mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW));
        }
@@ -1030,7 +1014,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    public void saveImage() {
        if (mImageShow.hasModifications()) {
            // Get the name of the album, to which the image will be saved
            File saveDir = SaveCopyTask.getFinalSaveDirectory(this, mSelectedImageUri);
            File saveDir = SaveImage.getFinalSaveDirectory(this, mSelectedImageUri);
            int bucketId = GalleryUtils.getBucketId(saveDir.getPath());
            String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null);
            showSavingProgress(albumName);
@@ -1063,9 +1047,4 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        return mSelectedImageUri;
    }

    static {
        System.loadLibrary("jni_filtershow_filters");
    }


}
+16 −6
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.gallery3d.filtershow.cache;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
@@ -33,6 +34,7 @@ import android.webkit.MimeTypeMap;

import com.adobe.xmp.XMPException;
import com.adobe.xmp.XMPMeta;
import com.android.gallery3d.R;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
@@ -286,17 +288,20 @@ public final class ImageLoader {
     * @param uri URI of image to open.
     * @param context context whose ContentResolver to use.
     * @param maxSideLength max side length of returned bitmap.
     * @param originalBounds set to the actual bounds of the stored bitmap.
     * @param originalBounds If not null, set to the actual bounds of the stored bitmap.
     * @param useMin use min or max side of the original image
     * @return downsampled bitmap or null if this operation failed.
     */
    public static Bitmap loadConstrainedBitmap(Uri uri, Context context, int maxSideLength,
            Rect originalBounds) {
        if (maxSideLength <= 0 || originalBounds == null || uri == null || context == null) {
            Rect originalBounds, boolean useMin) {
        if (maxSideLength <= 0 || uri == null || context == null) {
            throw new IllegalArgumentException("bad argument to getScaledBitmap");
        }
        // Get width and height of stored bitmap
        Rect storedBounds = loadBitmapBounds(context, uri);
        if (originalBounds != null) {
            originalBounds.set(storedBounds);
        }
        int w = storedBounds.width();
        int h = storedBounds.height();

@@ -306,7 +311,12 @@ public final class ImageLoader {
        }

        // Find best downsampling size
        int imageSide = Math.max(w, h);
        int imageSide = 0;
        if (useMin) {
            imageSide = Math.min(w, h);
        } else {
            imageSide = Math.max(w, h);
        }
        int sampleSize = 1;
        while (imageSide > maxSideLength) {
            imageSide >>>= 1;
@@ -336,7 +346,7 @@ public final class ImageLoader {
     */
    public static Bitmap loadOrientedConstrainedBitmap(Uri uri, Context context, int maxSideLength,
            int orientation, Rect originalBounds) {
        Bitmap bmap = loadConstrainedBitmap(uri, context, maxSideLength, originalBounds);
        Bitmap bmap = loadConstrainedBitmap(uri, context, maxSideLength, originalBounds, false);
        if (bmap != null) {
            bmap = orientBitmap(bmap, orientation);
        }
Loading