Make it harder to leak contexts

Change-Id: Ied60b6428bedb200d7b5b627e8196fbf2b4151e1
This commit is contained in:
Jason Sams
2015-03-18 17:04:18 -07:00
parent 1e68bac5f8
commit e16da12b7b

View File

@ -29,6 +29,7 @@ import android.util.Log;
import android.view.Surface;
import android.os.SystemProperties;
import android.os.Trace;
import java.util.ArrayList;
/**
* This class provides access to a RenderScript context, which controls RenderScript
@ -49,6 +50,12 @@ public class RenderScript {
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
static final boolean LOG_ENABLED = false;
static private ArrayList<RenderScript> mProcessContextList = new ArrayList<RenderScript>();
private boolean mIsProcessContext = false;
private int mContextFlags = 0;
private int mContextSdkVersion = 0;
private Context mApplicationContext;
/*
@ -1312,13 +1319,6 @@ public class RenderScript {
return mApplicationContext;
}
/**
* @hide
*/
public static RenderScript create(Context ctx, int sdkVersion) {
return create(ctx, sdkVersion, ContextType.NORMAL, CREATE_FLAG_NONE);
}
/**
* Create a RenderScript context.
*
@ -1326,7 +1326,7 @@ public class RenderScript {
* @param ctx The context.
* @return RenderScript
*/
public static RenderScript create(Context ctx, int sdkVersion, ContextType ct, int flags) {
private static RenderScript internalCreate(Context ctx, int sdkVersion, ContextType ct, int flags) {
if (!sInitialized) {
Log.e(LOG_TAG, "RenderScript.create() called when disabled; someone is likely to crash");
return null;
@ -1341,6 +1341,8 @@ public class RenderScript {
rs.mDev = rs.nDeviceCreate();
rs.mContext = rs.nContextCreate(rs.mDev, flags, sdkVersion, ct.mID);
rs.mContextType = ct;
rs.mContextFlags = flags;
rs.mContextSdkVersion = sdkVersion;
if (rs.mContext == 0) {
throw new RSDriverException("Failed to create RS context.");
}
@ -1350,7 +1352,9 @@ public class RenderScript {
}
/**
* Create a RenderScript context.
* calls create(cts, ContextType.NORMAL, CREATE_FLAG_NONE)
*
* See documentation for @create for details
*
* @param ctx The context.
* @return RenderScript
@ -1360,21 +1364,32 @@ public class RenderScript {
}
/**
* Create a RenderScript context.
* calls create(cts, ct, CREATE_FLAG_NONE)
*
* See documentation for @create for details
*
* @param ctx The context.
* @param ct The type of context to be created.
* @return RenderScript
*/
public static RenderScript create(Context ctx, ContextType ct) {
int v = ctx.getApplicationInfo().targetSdkVersion;
return create(ctx, v, ct, CREATE_FLAG_NONE);
return create(ctx, ct, CREATE_FLAG_NONE);
}
/**
* Create a RenderScript context.
* Gets or creates a RenderScript context of the specified type.
*
* The returned context will be cached for future reuse within
* the process. When an application is finished using
* RenderScript it should call releaseAllContexts()
*
* A process context is a context designed for easy creation and
* lifecycle management. Multiple calls to this function will
* return the same object provided they are called with the same
* options. This allows it to be used any time a RenderScript
* context is needed.
*
* Prior to API 23 this always created a new context.
*
* @param ctx The context.
* @param ct The type of context to be created.
@ -1383,9 +1398,75 @@ public class RenderScript {
*/
public static RenderScript create(Context ctx, ContextType ct, int flags) {
int v = ctx.getApplicationInfo().targetSdkVersion;
return create(ctx, v, ct, flags);
if (v < 23) {
return internalCreate(ctx, v, ct, flags);
}
synchronized (mProcessContextList) {
for (RenderScript prs : mProcessContextList) {
if ((prs.mContextType == ct) &&
(prs.mContextFlags == flags) &&
(prs.mContextSdkVersion == v)) {
return prs;
}
}
RenderScript prs = internalCreate(ctx, v, ct, flags);
prs.mIsProcessContext = true;
mProcessContextList.add(prs);
return prs;
}
}
/**
* @hide
*
* Releases all the process contexts. This is the same as
* calling .destroy() on each unique context retreived with
* create(...). If no contexts have been created this
* function does nothing.
*
* Typically you call this when your application is losing focus
* and will not be using a context for some time.
*
* This has no effect on a context created with
* createMultiContext()
*/
public static void releaseAllContexts() {
ArrayList<RenderScript> oldList;
synchronized (mProcessContextList) {
oldList = mProcessContextList;
mProcessContextList = new ArrayList<RenderScript>();
}
for (RenderScript prs : oldList) {
prs.mIsProcessContext = false;
prs.destroy();
}
oldList.clear();
}
/**
* Create a RenderScript context.
*
* This is an advanced function intended for applications which
* need to create more than one RenderScript context to be used
* at the same time.
*
* If you need a single context please use create()
*
* @hide
* @param ctx The context.
* @return RenderScript
*/
public static RenderScript createMultiContext(Context ctx, ContextType ct, int flags, int API_number) {
return internalCreate(ctx, API_number, ct, flags);
}
/**
* Print the currently available debugging information about the state of
* the RS context to the log.
@ -1442,8 +1523,16 @@ public class RenderScript {
* using this context or any objects belonging to this context is
* illegal.
*
* API 23+, this function is a NOP if the context was created
* with create(). Please use releaseAllContexts() to clean up
* contexts created with the create function.
*
*/
public void destroy() {
if (mIsProcessContext) {
// users cannot destroy a process context
return;
}
validate();
helpDestroy();
}