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