1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.renderscript; 18 19 import android.annotation.UnsupportedAppUsage; 20 import dalvik.system.CloseGuard; 21 import java.util.concurrent.locks.ReentrantReadWriteLock; 22 23 /** 24 * BaseObj is the base class for all RenderScript objects owned by a RS context. 25 * It is responsible for lifetime management and resource tracking. This class 26 * should not be used by a user application. 27 * 28 **/ 29 public class BaseObj { BaseObj(long id, RenderScript rs)30 BaseObj(long id, RenderScript rs) { 31 rs.validate(); 32 mRS = rs; 33 mID = id; 34 mDestroyed = false; 35 } 36 setID(long id)37 void setID(long id) { 38 if (mID != 0) { 39 throw new RSRuntimeException("Internal Error, reset of object ID."); 40 } 41 mID = id; 42 } 43 44 /** 45 * Lookup the native object ID for this object. Primarily used by the 46 * generated reflected code. 47 * 48 * @param rs Context to verify against internal context for 49 * match. 50 * 51 * @return long 52 */ getID(RenderScript rs)53 long getID(RenderScript rs) { 54 mRS.validate(); 55 if (mDestroyed) { 56 throw new RSInvalidStateException("using a destroyed object."); 57 } 58 if (mID == 0) { 59 throw new RSRuntimeException("Internal error: Object id 0."); 60 } 61 if ((rs != null) && (rs != mRS)) { 62 throw new RSInvalidStateException("using object with mismatched context."); 63 } 64 return mID; 65 } 66 checkValid()67 void checkValid() { 68 if (mID == 0) { 69 throw new RSIllegalArgumentException("Invalid object."); 70 } 71 } 72 73 private long mID; 74 final CloseGuard guard = CloseGuard.get(); 75 private boolean mDestroyed; 76 private String mName; 77 @UnsupportedAppUsage 78 RenderScript mRS; 79 80 /** 81 * setName assigns a name to an object. This object can later be looked up 82 * by this name. 83 * 84 * @param name The name to assign to the object. 85 */ setName(String name)86 public void setName(String name) { 87 if (name == null) { 88 throw new RSIllegalArgumentException( 89 "setName requires a string of non-zero length."); 90 } 91 if(name.length() < 1) { 92 throw new RSIllegalArgumentException( 93 "setName does not accept a zero length string."); 94 } 95 if(mName != null) { 96 throw new RSIllegalArgumentException( 97 "setName object already has a name."); 98 } 99 100 try { 101 byte[] bytes = name.getBytes("UTF-8"); 102 mRS.nAssignName(mID, bytes); 103 mName = name; 104 } catch (java.io.UnsupportedEncodingException e) { 105 throw new RuntimeException(e); 106 } 107 } 108 109 /** 110 * @return name of the renderscript object 111 */ getName()112 public String getName() { 113 return mName; 114 } 115 helpDestroy()116 private void helpDestroy() { 117 boolean shouldDestroy = false; 118 synchronized(this) { 119 if (!mDestroyed) { 120 shouldDestroy = true; 121 mDestroyed = true; 122 } 123 } 124 125 if (shouldDestroy) { 126 guard.close(); 127 // must include nObjDestroy in the critical section 128 ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock(); 129 rlock.lock(); 130 // AllocationAdapters are BaseObjs with an ID of 0 but should not be passed to nObjDestroy 131 if(mRS.isAlive() && mID != 0) { 132 mRS.nObjDestroy(mID); 133 } 134 rlock.unlock(); 135 mRS = null; 136 mID = 0; 137 } 138 } 139 finalize()140 protected void finalize() throws Throwable { 141 try { 142 if (guard != null) { 143 guard.warnIfOpen(); 144 } 145 helpDestroy(); 146 } finally { 147 super.finalize(); 148 } 149 } 150 151 /** 152 * Frees any native resources associated with this object. The 153 * primary use is to force immediate cleanup of resources when it is 154 * believed the GC will not respond quickly enough. 155 */ destroy()156 public void destroy() { 157 if(mDestroyed) { 158 throw new RSInvalidStateException("Object already destroyed."); 159 } 160 helpDestroy(); 161 } 162 163 /** 164 * If an object came from an a3d file, java fields need to be 165 * created with objects from the native layer 166 */ updateFromNative()167 void updateFromNative() { 168 mRS.validate(); 169 mName = mRS.nGetName(getID(mRS)); 170 } 171 172 /** 173 * Calculates the hash code value for a BaseObj. 174 * 175 * @return int 176 */ 177 @Override hashCode()178 public int hashCode() { 179 return (int)((mID & 0xfffffff) ^ (mID >> 32)); 180 } 181 182 /** 183 * Compare the current BaseObj with another BaseObj for equality. 184 * 185 * @param obj The object to check equality with. 186 * 187 * @return boolean 188 */ 189 @Override equals(Object obj)190 public boolean equals(Object obj) { 191 // Early-out check to see if both BaseObjs are actually the same 192 if (this == obj) 193 return true; 194 195 if (obj == null) { 196 return false; 197 } 198 199 if (getClass() != obj.getClass()) { 200 return false; 201 } 202 203 BaseObj b = (BaseObj) obj; 204 return mID == b.mID; 205 } 206 } 207 208