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