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

Commit be988e3a authored by Jim Miller's avatar Jim Miller Committed by Android (Google) Code Review
Browse files

Merge "Update RecentApplications to use shared Carousel widget."

parents decf6818 783cb60d
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -39,9 +39,6 @@ LOCAL_SRC_FILES += \
       core/java/android/webkit/EventLogTags.logtags \
       telephony/java/com/android/internal/telephony/EventLogTags.logtags \

# RenderScript files for internal widgets
LOCAL_SRC_FILES += $(call all-renderscript-files-under, core/java/com/android/internal/widget)

# The following filters out code we are temporarily not including at all.
# TODO: Move AWT and beans (and associated harmony code) back into libcore.
# TODO: Maybe remove javax.microedition entirely?
+0 −372
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.internal.widget;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.renderscript.*;
import android.renderscript.RenderScript.RSMessage;
import android.renderscript.Sampler.Value;
import android.renderscript.ProgramRaster.CullMode;
import android.util.Log;

import com.android.internal.R;

import static android.renderscript.Element.*;
import static android.renderscript.Sampler.Value.LINEAR;
import static android.renderscript.Sampler.Value.WRAP;
import static android.renderscript.Sampler.Value.CLAMP;

public class CarouselRS  {
    private static final int DEFAULT_VISIBLE_SLOTS = 1;
    private static final int DEFAULT_CARD_COUNT = 1;
    
    // Client messages *** THIS LIST MUST MATCH THOSE IN carousel.rs ***
    public static final int CMD_CARD_SELECTED = 100;
    public static final int CMD_REQUEST_TEXTURE = 200;
    public static final int CMD_INVALIDATE_TEXTURE = 210;
    public static final int CMD_REQUEST_GEOMETRY = 300;
    public static final int CMD_INVALIDATE_GEOMETRY = 310;
    public static final int CMD_ANIMATION_STARTED = 400;
    public static final int CMD_ANIMATION_FINISHED = 500;
    public static final int CMD_PING = 600; // for debugging
    
    private static final String TAG = "CarouselRS";
    private static final int DEFAULT_SLOT_COUNT = 10;
    private static final boolean MIPMAP = false;
    
    private RenderScriptGL mRS;
    private Resources mRes;
    private ScriptC_Carousel mScript;
    private ScriptField_Card mCards;
    private Sampler mSampler;
    private ProgramRaster mProgramRaster;
    private ProgramStore mProgramStore;
    private ProgramFragment mFragmentProgram;
    private ProgramVertex mVertexProgram;
    private ProgramRaster mRasterProgram;
    private CarouselCallback mCallback;
    private float[] mEyePoint = new float[3];
    private float[] mAtPoint = new float[3];
    private float[] mUp = new float[3];
    
    public static interface CarouselCallback {
        /**
         * Called when a card is selected
         * @param n the id of the card
         */
        void onCardSelected(int n);
        
        /**
         * Called when texture is needed for card n.  This happens when the given card becomes
         * visible.
         * @param n the id of the card
         */
        void onRequestTexture(int n);
        
        /**
         * Called when a texture is no longer needed for card n.  This happens when the card
         * goes out of view.
         * @param n the id of the card
         */
        void onInvalidateTexture(int n);
        
        /**
         * Called when geometry is needed for card n.
         * @param n the id of the card.
         */
        void onRequestGeometry(int n);
        
        /**
         * Called when geometry is no longer needed for card n. This happens when the card goes 
         * out of view.
         * @param n the id of the card
         */
        void onInvalidateGeometry(int n);
        
        /**
         * Called when card animation (e.g. a fling) has started.
         */
        void onAnimationStarted();
        
        /**
         * Called when card animation has stopped.
         */
        void onAnimationFinished();
    };
    
    private RSMessage mRsMessage = new RSMessage() {
        public void run() {
            if (mCallback == null) return;
            switch (mID) {
                case CMD_CARD_SELECTED:
                    mCallback.onCardSelected(mData[0]);
                    break;
                    
                case CMD_REQUEST_TEXTURE:
                    mCallback.onRequestTexture(mData[0]);
                    break;
                   
                case CMD_INVALIDATE_TEXTURE:
                    mCallback.onInvalidateTexture(mData[0]);
                    break;
                    
                case CMD_REQUEST_GEOMETRY:
                    mCallback.onRequestGeometry(mData[0]);
                    break;
                    
                case CMD_INVALIDATE_GEOMETRY:
                    mCallback.onInvalidateGeometry(mData[0]);
                    break;
                    
                case CMD_ANIMATION_STARTED:
                    mCallback.onAnimationStarted();
                    break;
                    
                case CMD_ANIMATION_FINISHED:
                    mCallback.onAnimationFinished();
                    break;
                    
                case CMD_PING:
                    Log.v(TAG, "PING...");
                    break;
                    
                default:
                    Log.e(TAG, "Unknown RSMessage: " + mID);
            }
        }
    };
    
    public void init(RenderScriptGL rs, Resources res) {
        mRS = rs;
        mRes = res;

        // create the script object
        mScript = new ScriptC_Carousel(mRS, mRes, R.raw.carousel, true);
        mRS.mMessageCallback = mRsMessage;

        initProgramStore();
        initFragmentProgram();
        initRasterProgram();
        initVertexProgram();
        
        setSlotCount(DEFAULT_SLOT_COUNT);
        setVisibleSlots(DEFAULT_VISIBLE_SLOTS);
        createCards(DEFAULT_CARD_COUNT);
        
        setStartAngle(0.0f);
        setRadius(1.0f);
        
        // update the camera
        boolean pcam = true;
        if (pcam) {
            float eye[] = { 20.6829f, 2.77081f, 16.7314f };
            float at[] = { 14.7255f, -3.40001f, -1.30184f };
            float up[] = { 0.0f, 1.0f, 0.0f };
            setLookAt(eye, at, up);
            setRadius(20.0f);
            // Fov: 25
        } else {
            mScript.invoke_lookAt(2.5f, 2.0f, 2.5f, 0.0f, -0.75f, 0.0f,  0.0f, 1.0f, 0.0f);
            mScript.set_cardRotation(0.0f);
            setRadius(1.5f);
        }

        resumeRendering();
    }

    public void setLookAt(float[] eye, float[] at, float[] up) {
        for (int i = 0; i < 3; i++) {
            mEyePoint[i] = eye[i];
            mAtPoint[i] = at[i];
            mUp[i] = up[i];
        }
        mScript.invoke_lookAt(eye[0], eye[1], eye[2], at[0], at[1], at[2], up[0], up[1], up[2]);
    }

    public void setRadius(float radius) {
        mScript.set_radius(radius);
    }

    private void initVertexProgram() {
        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
        mVertexProgram = pvb.create();
        ProgramVertex.MatrixAllocation pva = new ProgramVertex.MatrixAllocation(mRS);
        mVertexProgram.bindAllocation(pva);
        pva.setupProjectionNormalized(1, 1);
        mScript.set_vertexProgram(mVertexProgram);
    }

    private void initRasterProgram() {
        ProgramRaster.Builder programRasterBuilder = new ProgramRaster.Builder(mRS);
        mRasterProgram = programRasterBuilder.create();
        //mRasterProgram.setCullMode(CullMode.NONE);
        mScript.set_rasterProgram(mRasterProgram);
    }

    private void initFragmentProgram() {
        Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
        sampleBuilder.setMin(Value.LINEAR_MIP_LINEAR);
        sampleBuilder.setMag(LINEAR);
        sampleBuilder.setWrapS(CLAMP);
        sampleBuilder.setWrapT(CLAMP);
        mSampler = sampleBuilder.create();
        ProgramFragment.Builder fragmentBuilder = new ProgramFragment.Builder(mRS);
        fragmentBuilder.setTexture(ProgramFragment.Builder.EnvMode.DECAL,
                           ProgramFragment.Builder.Format.RGBA, 0);
        mFragmentProgram = fragmentBuilder.create();
        mFragmentProgram.bindSampler(mSampler, 0);
        mScript.set_fragmentProgram(mFragmentProgram);
    }

    private void initProgramStore() {
        ProgramStore.Builder programStoreBuilder = new ProgramStore.Builder(mRS, null, null);
        programStoreBuilder.setDepthFunc(ProgramStore.DepthFunc.LESS);
        programStoreBuilder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA, 
                ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
        programStoreBuilder.setDitherEnable(false);
        programStoreBuilder.setDepthMask(true);
        mProgramStore = programStoreBuilder.create();
        mScript.set_programStore(mProgramStore);
    }
    
    public void createCards(int count)
    {
        mCards = count > 0 ? new ScriptField_Card(mRS, count) : null;
        mScript.bind_cards(mCards);
        mScript.invoke_createCards(count);
    }
    
    public void setVisibleSlots(int count)
    {
        mScript.set_visibleSlotCount(count);
    }
    
    public void setDefaultBitmap(Bitmap bitmap)
    {
        mScript.set_defaultTexture(allocationFromBitmap(bitmap, MIPMAP));
    }
    
    public void setLoadingBitmap(Bitmap bitmap)
    {
        mScript.set_loadingTexture(allocationFromBitmap(bitmap, MIPMAP));
    }
    
    public void setDefaultGeometry(Mesh mesh)
    {
        mScript.set_defaultGeometry(mesh);
    }
    
    public void setLoadingGeometry(Mesh mesh)
    {
        mScript.set_loadingGeometry(mesh);
    }
    
    public void setStartAngle(float theta)
    {
        mScript.set_startAngle(theta);
    }
    
    public void setCallback(CarouselCallback callback)
    {
        mCallback = callback;
    }
    
    private Allocation allocationFromBitmap(Bitmap bitmap, boolean mipmap)
    {
        if (bitmap == null) return null;
        Allocation allocation = Allocation.createFromBitmap(mRS, bitmap, RGB_565(mRS), mipmap);
        allocation.uploadToTexture(0);
        return allocation;
    }
    
    public void setTexture(int n, Bitmap bitmap)
    {
        ScriptField_Card.Item item = mCards.get(n);
        if (item == null) {
            Log.v(TAG, "setTexture(): no item at index " + n);
            item = new ScriptField_Card.Item();
        }
        if (bitmap != null) {
            Log.v(TAG, "creating new bitmap");
            item.texture = Allocation.createFromBitmap(mRS, bitmap, RGB_565(mRS), MIPMAP);
            Log.v(TAG, "uploadToTexture(" + n + ")");
            item.texture.uploadToTexture(0);
            Log.v(TAG, "done...");
        } else {
            if (item.texture != null) {
                Log.v(TAG, "unloading texture " + n);
                // Don't wait for GC to free native memory.
                // Only works if textures are not shared.
                item.texture.destroy(); 
                item.texture = null;
            }
        }
        mCards.set(item, n, false); // This is primarily used for reference counting.
        mScript.invoke_setTexture(n, item.texture);
    }
    
    public void setGeometry(int n, Mesh geometry)
    {
        final boolean mipmap = false;
        ScriptField_Card.Item item = mCards.get(n);
        if (item == null) {
            Log.v(TAG, "setGeometry(): no item at index " + n);
            item = new ScriptField_Card.Item();
        }
        if (geometry != null) {
            item.geometry = geometry;
        } else {
            Log.v(TAG, "unloading geometry " + n);
            if (item.geometry != null) {
                // item.geometry.destroy(); 
                item.geometry = null;
            }
        }
        mCards.set(item, n, false);
        mScript.invoke_setGeometry(n, item.geometry);
    }

    public void pauseRendering() {
        // Used to update multiple states at once w/o redrawing for each.
        mRS.contextBindRootScript(null);
    }
    
    public void resumeRendering() {
        mRS.contextBindRootScript(mScript);
    }
    
    public void doMotion(float x, float y) {
        mScript.invoke_doMotion(x,y);
    }
    
    public void doSelection(float x, float y) {
        mScript.invoke_doSelection(x, y);
    }

    public void doStart(float x, float y) {
        mScript.invoke_doStart(x, y);
    }

    public void doStop(float x, float y) {
        mScript.invoke_doStop(x, y);
    }

    public void setSlotCount(int n) {
        mScript.set_slotCount(n);
    }
}
+0 −266
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.internal.widget;

import com.android.internal.R;
import com.android.internal.widget.CarouselRS.CarouselCallback;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.Bitmap.Config;
import android.renderscript.FileA3D;
import android.renderscript.Mesh;
import android.renderscript.RSSurfaceView;
import android.renderscript.RenderScriptGL;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class CarouselView extends RSSurfaceView {
    private static final boolean USE_DEPTH_BUFFER = true;
    private final int DEFAULT_SLOT_COUNT = 10;
    private final Bitmap DEFAULT_BITMAP = Bitmap.createBitmap(1, 1, Config.RGB_565);
    private static final String TAG = "CarouselView";
    private CarouselRS mRenderScript;
    private RenderScriptGL mRS;
    private Context mContext;
    private boolean mTracking;
    private Bitmap mDefaultBitmap;
    private Bitmap mLoadingBitmap;
    private Mesh mDefaultGeometry;
    private Mesh mLoadingGeometry;
    private int mCardCount = 0;
    private int mVisibleSlots = 0;
    private float mStartAngle;
    private int mSlotCount = DEFAULT_SLOT_COUNT;

    public CarouselView(Context context) {
        this(context, null);
    }

    /**
     * Constructor used when this widget is created from a layout file.
     */
    public CarouselView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        boolean useDepthBuffer = true;
        mRS = createRenderScript(USE_DEPTH_BUFFER);
        mRenderScript = new CarouselRS();
        mRenderScript.init(mRS, getResources());
        // TODO: add parameters to layout
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        super.surfaceChanged(holder, format, w, h);
        //mRS.contextSetSurface(w, h, holder.getSurface());
        mRenderScript.init(mRS, getResources());
        setSlotCount(mSlotCount);
        createCards(mCardCount);
        setVisibleSlots(mVisibleSlots);
        setCallback(mCarouselCallback);
        setDefaultBitmap(mDefaultBitmap);
        setLoadingBitmap(mLoadingBitmap);
        setDefaultGeometry(mDefaultGeometry);
        setLoadingGeometry(mLoadingGeometry);
        setStartAngle(mStartAngle);
    }

    /**
     * Loads geometry from a resource id.
     * 
     * @param resId
     * @return the loaded mesh or null if it cannot be loaded
     */
    public Mesh loadGeometry(int resId) {
        Resources res = mContext.getResources();
        FileA3D model = FileA3D.createFromResource(mRS, res, resId);
        FileA3D.IndexEntry entry = model.getIndexEntry(0);
        if(entry == null || entry.getClassID() != FileA3D.ClassID.MESH) {
            return null;
        }
        return (Mesh) entry.getObject();
    }
    
    /**
     * Load A3D file from resource.  If resId == 0, will clear geometry for this item.
     * @param n
     * @param resId
     */
    public void setGeometryForItem(int n, Mesh mesh) {
        mRenderScript.setGeometry(n, mesh);
    }
    
    public void setSlotCount(int n) {
        mSlotCount = n;
        if (mRenderScript != null) {
            mRenderScript.setSlotCount(n);
        }
    }

    public void setVisibleSlots(int n) {
        mVisibleSlots = n;
        if (mRenderScript != null) {
            mRenderScript.setVisibleSlots(n);
        }
    }

    public void createCards(int n) {
        mCardCount = n;
        if (mRenderScript != null) {
            mRenderScript.createCards(n);
        }
    }
    
    public void setTextureForItem(int n, Bitmap bitmap) {
        if (mRenderScript != null) {
            Log.v(TAG, "setTextureForItem(" + n + ")");
            mRenderScript.setTexture(n, bitmap); 
            Log.v(TAG, "done");
        }
    }

    public void setDefaultBitmap(Bitmap bitmap) {
        mDefaultBitmap = bitmap; 
        if (mRenderScript != null) {
            mRenderScript.setDefaultBitmap(bitmap);
        }
    }
    
    public void setLoadingBitmap(Bitmap bitmap) {
        mLoadingBitmap = bitmap;
        if (mRenderScript != null) {
            mRenderScript.setLoadingBitmap(bitmap);
        }
    }
    
    public void setDefaultGeometry(Mesh mesh) {
        mDefaultGeometry = mesh;
        if (mRenderScript != null) {
            mRenderScript.setDefaultGeometry(mesh);
        }
    }
    
    public void setLoadingGeometry(Mesh mesh) {
        mLoadingGeometry = mesh;
        if (mRenderScript != null) {
            mRenderScript.setLoadingGeometry(mesh);
        }
    }
    
    public void setCallback(CarouselCallback callback)
    {
        mCarouselCallback = callback;
        if (mRenderScript != null) {
            mRenderScript.setCallback(callback);
        }
    }

    public void setStartAngle(float angle)
    {
        mStartAngle = angle;
        if (mRenderScript != null) {
            mRenderScript.setStartAngle(angle);
        }
    }
    
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if(mRS != null) {
            mRS = null;
            destroyRenderScript();
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (mRS == null) {
            mRS = createRenderScript(USE_DEPTH_BUFFER);
        }
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        final float x = event.getX();
        final float y = event.getY();
        
        if (mRenderScript == null) {
            return true;
        }

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mTracking = true;
                mRenderScript.doStart(x, y);
                break;
                
            case MotionEvent.ACTION_MOVE:
                if (mTracking) {
                    mRenderScript.doMotion(x, y);
                }
                break;
                
            case MotionEvent.ACTION_UP:
                mRenderScript.doStop(x, y);
                mTracking = false;
                break;
        }

        return true;
    }
    
    private final CarouselCallback DEBUG_CALLBACK = new CarouselCallback() {
        public void onAnimationStarted() {
            Log.v(TAG, "onAnimationStarted()");
        }
        
        public void onAnimationFinished() {
            Log.v(TAG, "onAnimationFinished()");
        }

        public void onCardSelected(int n) {
            Log.v(TAG, "onCardSelected(" + n + ")");
        }

        public void onRequestGeometry(int n) {
            Log.v(TAG, "onRequestGeometry(" + n + ")");
        }

        public void onInvalidateGeometry(int n) {
            Log.v(TAG, "onInvalidateGeometry(" + n + ")");
        }
        
        public void onRequestTexture(final int n) {
            Log.v(TAG, "onRequestTexture(" + n + ")");
        }

        public void onInvalidateTexture(int n) {
            Log.v(TAG, "onInvalidateTexture(" + n + ")");
        }

    };
    
    private CarouselCallback mCarouselCallback = DEBUG_CALLBACK;
}
+0 −788

File deleted.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -36,12 +36,12 @@ LOCAL_EXPORT_PACKAGE_RESOURCES := true
# Include resources generated by system RenderScript files.
framework_GENERATED_SOURCE_DIR := $(call intermediates-dir-for,JAVA_LIBRARIES,framework,,COMMON)/src
framework_RenderScript_STAMP_FILE := $(framework_GENERATED_SOURCE_DIR)/RenderScript.stamp
LOCAL_RESOURCE_DIR := $(framework_GENERATED_SOURCE_DIR)/renderscript/res $(LOCAL_PATH)/res
#LOCAL_RESOURCE_DIR := $(framework_GENERATED_SOURCE_DIR)/renderscript/res $(LOCAL_PATH)/res

include $(BUILD_PACKAGE)

# Make sure the system .rs files get compiled before building the package-export.apk.
$(resource_export_package): $(framework_RenderScript_STAMP_FILE)
# $(resource_export_package): $(framework_RenderScript_STAMP_FILE)

# define a global intermediate target that other module may depend on.
.PHONY: framework-res-package-target
Loading