1 /* 2 * Copyright (C) 2006 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.content.res; 18 19 import static android.content.res.Resources.ID_NULL; 20 import static android.system.OsConstants.EINVAL; 21 22 import android.annotation.AnyRes; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.compat.annotation.UnsupportedAppUsage; 26 import android.os.Build; 27 import android.util.TypedValue; 28 29 import com.android.internal.annotations.VisibleForTesting; 30 import com.android.internal.util.XmlUtils; 31 32 import dalvik.annotation.optimization.CriticalNative; 33 import dalvik.annotation.optimization.FastNative; 34 35 import org.xmlpull.v1.XmlPullParserException; 36 37 import java.io.IOException; 38 import java.io.InputStream; 39 import java.io.Reader; 40 41 /** 42 * Wrapper around a compiled XML file. 43 * 44 * {@hide} 45 */ 46 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 47 public final class XmlBlock implements AutoCloseable { 48 private static final boolean DEBUG=false; 49 50 @UnsupportedAppUsage XmlBlock(byte[] data)51 public XmlBlock(byte[] data) { 52 mAssets = null; 53 mNative = nativeCreate(data, 0, data.length); 54 mStrings = new StringBlock(nativeGetStringBlock(mNative), false); 55 } 56 XmlBlock(byte[] data, int offset, int size)57 public XmlBlock(byte[] data, int offset, int size) { 58 mAssets = null; 59 mNative = nativeCreate(data, offset, size); 60 mStrings = new StringBlock(nativeGetStringBlock(mNative), false); 61 } 62 63 @Override close()64 public void close() { 65 synchronized (this) { 66 if (mOpen) { 67 mOpen = false; 68 decOpenCountLocked(); 69 } 70 } 71 } 72 decOpenCountLocked()73 private void decOpenCountLocked() { 74 mOpenCount--; 75 if (mOpenCount == 0) { 76 mStrings.close(); 77 nativeDestroy(mNative); 78 mNative = 0; 79 if (mAssets != null) { 80 mAssets.xmlBlockGone(hashCode()); 81 } 82 } 83 } 84 85 @UnsupportedAppUsage newParser()86 public XmlResourceParser newParser() { 87 return newParser(ID_NULL); 88 } 89 newParser(@nyRes int resId)90 public XmlResourceParser newParser(@AnyRes int resId) { 91 synchronized (this) { 92 if (mNative != 0) { 93 return new Parser(nativeCreateParseState(mNative, resId), this); 94 } 95 return null; 96 } 97 } 98 99 /** 100 * Reference Error.h UNEXPECTED_NULL 101 */ 102 private static final int ERROR_NULL_DOCUMENT = Integer.MIN_VALUE + 8; 103 /** 104 * The reason not to ResXMLParser::BAD_DOCUMENT which is -1 is that other places use the same 105 * value. Reference Error.h BAD_VALUE = -EINVAL 106 */ 107 private static final int ERROR_BAD_DOCUMENT = -EINVAL; 108 109 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 110 public final class Parser implements XmlResourceParser { Parser(long parseState, XmlBlock block)111 Parser(long parseState, XmlBlock block) { 112 mParseState = parseState; 113 mBlock = block; 114 block.mOpenCount++; 115 } 116 117 @AnyRes getSourceResId()118 public int getSourceResId() { 119 return nativeGetSourceResId(mParseState); 120 } 121 setFeature(String name, boolean state)122 public void setFeature(String name, boolean state) throws XmlPullParserException { 123 if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) { 124 return; 125 } 126 if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) { 127 return; 128 } 129 throw new XmlPullParserException("Unsupported feature: " + name); 130 } getFeature(String name)131 public boolean getFeature(String name) { 132 if (FEATURE_PROCESS_NAMESPACES.equals(name)) { 133 return true; 134 } 135 if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) { 136 return true; 137 } 138 return false; 139 } setProperty(String name, Object value)140 public void setProperty(String name, Object value) throws XmlPullParserException { 141 throw new XmlPullParserException("setProperty() not supported"); 142 } getProperty(String name)143 public Object getProperty(String name) { 144 return null; 145 } setInput(Reader in)146 public void setInput(Reader in) throws XmlPullParserException { 147 throw new XmlPullParserException("setInput() not supported"); 148 } setInput(InputStream inputStream, String inputEncoding)149 public void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException { 150 throw new XmlPullParserException("setInput() not supported"); 151 } defineEntityReplacementText(String entityName, String replacementText)152 public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException { 153 throw new XmlPullParserException("defineEntityReplacementText() not supported"); 154 } getNamespacePrefix(int pos)155 public String getNamespacePrefix(int pos) throws XmlPullParserException { 156 throw new XmlPullParserException("getNamespacePrefix() not supported"); 157 } getInputEncoding()158 public String getInputEncoding() { 159 return null; 160 } getNamespace(String prefix)161 public String getNamespace(String prefix) { 162 throw new RuntimeException("getNamespace() not supported"); 163 } getNamespaceCount(int depth)164 public int getNamespaceCount(int depth) throws XmlPullParserException { 165 throw new XmlPullParserException("getNamespaceCount() not supported"); 166 } getPositionDescription()167 public String getPositionDescription() { 168 return "Binary XML file line #" + getLineNumber(); 169 } getNamespaceUri(int pos)170 public String getNamespaceUri(int pos) throws XmlPullParserException { 171 throw new XmlPullParserException("getNamespaceUri() not supported"); 172 } getColumnNumber()173 public int getColumnNumber() { 174 return -1; 175 } getDepth()176 public int getDepth() { 177 return mDepth; 178 } 179 @Nullable getText()180 public String getText() { 181 int id = nativeGetText(mParseState); 182 return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : null; 183 } getLineNumber()184 public int getLineNumber() { 185 final int lineNumber = nativeGetLineNumber(mParseState); 186 if (lineNumber == ERROR_NULL_DOCUMENT) { 187 throw new NullPointerException("Null document"); 188 } 189 return lineNumber; 190 } getEventType()191 public int getEventType() throws XmlPullParserException { 192 return mEventType; 193 } isWhitespace()194 public boolean isWhitespace() throws XmlPullParserException { 195 // whitespace was stripped by aapt. 196 return false; 197 } getPrefix()198 public String getPrefix() { 199 throw new RuntimeException("getPrefix not supported"); 200 } getTextCharacters(int[] holderForStartAndLength)201 public char[] getTextCharacters(int[] holderForStartAndLength) { 202 String txt = getText(); 203 char[] chars = null; 204 if (txt != null) { 205 holderForStartAndLength[0] = 0; 206 holderForStartAndLength[1] = txt.length(); 207 chars = new char[txt.length()]; 208 txt.getChars(0, txt.length(), chars, 0); 209 } 210 return chars; 211 } 212 @Nullable getNamespace()213 public String getNamespace() { 214 int id = nativeGetNamespace(mParseState); 215 return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : ""; 216 } 217 @Nullable getName()218 public String getName() { 219 int id = nativeGetName(mParseState); 220 return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : null; 221 } 222 @NonNull getAttributeNamespace(int index)223 public String getAttributeNamespace(int index) { 224 final int id = nativeGetAttributeNamespace(mParseState, index); 225 if (id == ERROR_NULL_DOCUMENT) { 226 throw new NullPointerException("Null document"); 227 } 228 if (DEBUG) System.out.println("getAttributeNamespace of " + index + " = " + id); 229 if (id >= 0) return getSequenceString(mStrings.getSequence(id)); 230 else if (id == -1) return ""; 231 throw new IndexOutOfBoundsException(String.valueOf(index)); 232 } 233 @NonNull getAttributeName(int index)234 public String getAttributeName(int index) { 235 final int id = nativeGetAttributeName(mParseState, index); 236 if (DEBUG) System.out.println("getAttributeName of " + index + " = " + id); 237 if (id == ERROR_NULL_DOCUMENT) { 238 throw new NullPointerException("Null document"); 239 } 240 if (id >= 0) return getSequenceString(mStrings.getSequence(id)); 241 throw new IndexOutOfBoundsException(String.valueOf(index)); 242 } getAttributePrefix(int index)243 public String getAttributePrefix(int index) { 244 throw new RuntimeException("getAttributePrefix not supported"); 245 } isEmptyElementTag()246 public boolean isEmptyElementTag() throws XmlPullParserException { 247 // XXX Need to detect this. 248 return false; 249 } getAttributeCount()250 public int getAttributeCount() { 251 if (mEventType == START_TAG) { 252 final int count = nativeGetAttributeCount(mParseState); 253 if (count == ERROR_NULL_DOCUMENT) { 254 throw new NullPointerException("Null document"); 255 } 256 return count; 257 } else { 258 return -1; 259 } 260 } 261 @NonNull getAttributeValue(int index)262 public String getAttributeValue(int index) { 263 final int id = nativeGetAttributeStringValue(mParseState, index); 264 if (id == ERROR_NULL_DOCUMENT) { 265 throw new NullPointerException("Null document"); 266 } 267 if (DEBUG) System.out.println("getAttributeValue of " + index + " = " + id); 268 if (id >= 0) return getSequenceString(mStrings.getSequence(id)); 269 270 // May be some other type... check and try to convert if so. 271 final int t = nativeGetAttributeDataType(mParseState, index); 272 if (t == ERROR_NULL_DOCUMENT) { 273 throw new NullPointerException("Null document"); 274 } 275 if (t == TypedValue.TYPE_NULL) { 276 throw new IndexOutOfBoundsException(String.valueOf(index)); 277 } 278 279 final int v = nativeGetAttributeData(mParseState, index); 280 if (v == ERROR_NULL_DOCUMENT) { 281 throw new NullPointerException("Null document"); 282 } 283 return TypedValue.coerceToString(t, v); 284 } getAttributeType(int index)285 public String getAttributeType(int index) { 286 return "CDATA"; 287 } isAttributeDefault(int index)288 public boolean isAttributeDefault(int index) { 289 return false; 290 } nextToken()291 public int nextToken() throws XmlPullParserException,IOException { 292 return next(); 293 } getAttributeValue(String namespace, String name)294 public String getAttributeValue(String namespace, String name) { 295 int idx = nativeGetAttributeIndex(mParseState, namespace, name); 296 if (idx >= 0) { 297 if (DEBUG) System.out.println("getAttributeName of " 298 + namespace + ":" + name + " index = " + idx); 299 if (DEBUG) System.out.println( 300 "Namespace=" + getAttributeNamespace(idx) 301 + "Name=" + getAttributeName(idx) 302 + ", Value=" + getAttributeValue(idx)); 303 return getAttributeValue(idx); 304 } 305 return null; 306 } next()307 public int next() throws XmlPullParserException,IOException { 308 if (!mStarted) { 309 mStarted = true; 310 return START_DOCUMENT; 311 } 312 if (mParseState == 0) { 313 return END_DOCUMENT; 314 } 315 int ev = nativeNext(mParseState); 316 if (ev == ERROR_BAD_DOCUMENT) { 317 throw new XmlPullParserException("Corrupt XML binary file"); 318 } 319 if (mDecNextDepth) { 320 mDepth--; 321 mDecNextDepth = false; 322 } 323 switch (ev) { 324 case START_TAG: 325 mDepth++; 326 break; 327 case END_TAG: 328 mDecNextDepth = true; 329 break; 330 } 331 mEventType = ev; 332 if (ev == END_DOCUMENT) { 333 // Automatically close the parse when we reach the end of 334 // a document, since the standard XmlPullParser interface 335 // doesn't have such an API so most clients will leave us 336 // dangling. 337 close(); 338 } 339 return ev; 340 } require(int type, String namespace, String name)341 public void require(int type, String namespace, String name) throws XmlPullParserException,IOException { 342 if (type != getEventType() 343 || (namespace != null && !namespace.equals( getNamespace () ) ) 344 || (name != null && !name.equals( getName() ) ) ) 345 throw new XmlPullParserException( "expected "+ TYPES[ type ]+getPositionDescription()); 346 } nextText()347 public String nextText() throws XmlPullParserException,IOException { 348 if(getEventType() != START_TAG) { 349 throw new XmlPullParserException( 350 getPositionDescription() 351 + ": parser must be on START_TAG to read next text", this, null); 352 } 353 int eventType = next(); 354 if(eventType == TEXT) { 355 String result = getText(); 356 eventType = next(); 357 if(eventType != END_TAG) { 358 throw new XmlPullParserException( 359 getPositionDescription() 360 + ": event TEXT it must be immediately followed by END_TAG", this, null); 361 } 362 return result; 363 } else if(eventType == END_TAG) { 364 return ""; 365 } else { 366 throw new XmlPullParserException( 367 getPositionDescription() 368 + ": parser must be on START_TAG or TEXT to read text", this, null); 369 } 370 } nextTag()371 public int nextTag() throws XmlPullParserException,IOException { 372 int eventType = next(); 373 if(eventType == TEXT && isWhitespace()) { // skip whitespace 374 eventType = next(); 375 } 376 if (eventType != START_TAG && eventType != END_TAG) { 377 throw new XmlPullParserException( 378 getPositionDescription() 379 + ": expected start or end tag", this, null); 380 } 381 return eventType; 382 } 383 getAttributeNameResource(int index)384 public int getAttributeNameResource(int index) { 385 final int resourceNameId = nativeGetAttributeResource(mParseState, index); 386 if (resourceNameId == ERROR_NULL_DOCUMENT) { 387 throw new NullPointerException("Null document"); 388 } 389 return resourceNameId; 390 } 391 getAttributeListValue(String namespace, String attribute, String[] options, int defaultValue)392 public int getAttributeListValue(String namespace, String attribute, 393 String[] options, int defaultValue) { 394 int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); 395 if (idx >= 0) { 396 return getAttributeListValue(idx, options, defaultValue); 397 } 398 return defaultValue; 399 } getAttributeBooleanValue(String namespace, String attribute, boolean defaultValue)400 public boolean getAttributeBooleanValue(String namespace, String attribute, 401 boolean defaultValue) { 402 int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); 403 if (idx >= 0) { 404 return getAttributeBooleanValue(idx, defaultValue); 405 } 406 return defaultValue; 407 } getAttributeResourceValue(String namespace, String attribute, int defaultValue)408 public int getAttributeResourceValue(String namespace, String attribute, 409 int defaultValue) { 410 int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); 411 if (idx >= 0) { 412 return getAttributeResourceValue(idx, defaultValue); 413 } 414 return defaultValue; 415 } getAttributeIntValue(String namespace, String attribute, int defaultValue)416 public int getAttributeIntValue(String namespace, String attribute, 417 int defaultValue) { 418 int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); 419 if (idx >= 0) { 420 return getAttributeIntValue(idx, defaultValue); 421 } 422 return defaultValue; 423 } getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue)424 public int getAttributeUnsignedIntValue(String namespace, String attribute, 425 int defaultValue) 426 { 427 int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); 428 if (idx >= 0) { 429 return getAttributeUnsignedIntValue(idx, defaultValue); 430 } 431 return defaultValue; 432 } getAttributeFloatValue(String namespace, String attribute, float defaultValue)433 public float getAttributeFloatValue(String namespace, String attribute, 434 float defaultValue) { 435 int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); 436 if (idx >= 0) { 437 return getAttributeFloatValue(idx, defaultValue); 438 } 439 return defaultValue; 440 } 441 getAttributeListValue(int idx, String[] options, int defaultValue)442 public int getAttributeListValue(int idx, 443 String[] options, int defaultValue) { 444 final int t = nativeGetAttributeDataType(mParseState, idx); 445 if (t == ERROR_NULL_DOCUMENT) { 446 throw new NullPointerException("Null document"); 447 } 448 final int v = nativeGetAttributeData(mParseState, idx); 449 if (v == ERROR_NULL_DOCUMENT) { 450 throw new NullPointerException("Null document"); 451 } 452 if (t == TypedValue.TYPE_STRING) { 453 return XmlUtils.convertValueToList( 454 mStrings.getSequence(v), options, defaultValue); 455 } 456 return v; 457 } getAttributeBooleanValue(int idx, boolean defaultValue)458 public boolean getAttributeBooleanValue(int idx, 459 boolean defaultValue) { 460 final int t = nativeGetAttributeDataType(mParseState, idx); 461 if (t == ERROR_NULL_DOCUMENT) { 462 throw new NullPointerException("Null document"); 463 } 464 // Note: don't attempt to convert any other types, because 465 // we want to count on aapt doing the conversion for us. 466 if (t >= TypedValue.TYPE_FIRST_INT && t <= TypedValue.TYPE_LAST_INT) { 467 final int v = nativeGetAttributeData(mParseState, idx); 468 if (v == ERROR_NULL_DOCUMENT) { 469 throw new NullPointerException("Null document"); 470 } 471 return v != 0; 472 } 473 return defaultValue; 474 } getAttributeResourceValue(int idx, int defaultValue)475 public int getAttributeResourceValue(int idx, int defaultValue) { 476 final int t = nativeGetAttributeDataType(mParseState, idx); 477 if (t == ERROR_NULL_DOCUMENT) { 478 throw new NullPointerException("Null document"); 479 } 480 // Note: don't attempt to convert any other types, because 481 // we want to count on aapt doing the conversion for us. 482 if (t == TypedValue.TYPE_REFERENCE) { 483 final int v = nativeGetAttributeData(mParseState, idx); 484 if (v == ERROR_NULL_DOCUMENT) { 485 throw new NullPointerException("Null document"); 486 } 487 return v; 488 } 489 return defaultValue; 490 } getAttributeIntValue(int idx, int defaultValue)491 public int getAttributeIntValue(int idx, int defaultValue) { 492 final int t = nativeGetAttributeDataType(mParseState, idx); 493 if (t == ERROR_NULL_DOCUMENT) { 494 throw new NullPointerException("Null document"); 495 } 496 // Note: don't attempt to convert any other types, because 497 // we want to count on aapt doing the conversion for us. 498 if (t >= TypedValue.TYPE_FIRST_INT && t <= TypedValue.TYPE_LAST_INT) { 499 final int v = nativeGetAttributeData(mParseState, idx); 500 if (v == ERROR_NULL_DOCUMENT) { 501 throw new NullPointerException("Null document"); 502 } 503 return v; 504 } 505 return defaultValue; 506 } getAttributeUnsignedIntValue(int idx, int defaultValue)507 public int getAttributeUnsignedIntValue(int idx, int defaultValue) { 508 int t = nativeGetAttributeDataType(mParseState, idx); 509 if (t == ERROR_NULL_DOCUMENT) { 510 throw new NullPointerException("Null document"); 511 } 512 // Note: don't attempt to convert any other types, because 513 // we want to count on aapt doing the conversion for us. 514 if (t >= TypedValue.TYPE_FIRST_INT && t <= TypedValue.TYPE_LAST_INT) { 515 final int v = nativeGetAttributeData(mParseState, idx); 516 if (v == ERROR_NULL_DOCUMENT) { 517 throw new NullPointerException("Null document"); 518 } 519 return v; 520 } 521 return defaultValue; 522 } getAttributeFloatValue(int idx, float defaultValue)523 public float getAttributeFloatValue(int idx, float defaultValue) { 524 final int t = nativeGetAttributeDataType(mParseState, idx); 525 if (t == ERROR_NULL_DOCUMENT) { 526 throw new NullPointerException("Null document"); 527 } 528 // Note: don't attempt to convert any other types, because 529 // we want to count on aapt doing the conversion for us. 530 if (t == TypedValue.TYPE_FLOAT) { 531 final int v = nativeGetAttributeData(mParseState, idx); 532 if (v == ERROR_NULL_DOCUMENT) { 533 throw new NullPointerException("Null document"); 534 } 535 return Float.intBitsToFloat(v); 536 } 537 throw new RuntimeException("not a float!"); 538 } 539 @Nullable getIdAttribute()540 public String getIdAttribute() { 541 final int id = nativeGetIdAttribute(mParseState); 542 if (id == ERROR_NULL_DOCUMENT) { 543 throw new NullPointerException("Null document"); 544 } 545 return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : null; 546 } 547 @Nullable getClassAttribute()548 public String getClassAttribute() { 549 final int id = nativeGetClassAttribute(mParseState); 550 if (id == ERROR_NULL_DOCUMENT) { 551 throw new NullPointerException("Null document"); 552 } 553 return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : null; 554 } 555 getIdAttributeResourceValue(int defaultValue)556 public int getIdAttributeResourceValue(int defaultValue) { 557 //todo: create and use native method 558 return getAttributeResourceValue(null, "id", defaultValue); 559 } 560 getStyleAttribute()561 public int getStyleAttribute() { 562 final int styleAttributeId = nativeGetStyleAttribute(mParseState); 563 if (styleAttributeId == ERROR_NULL_DOCUMENT) { 564 throw new NullPointerException("Null document"); 565 } 566 return styleAttributeId; 567 } 568 getSequenceString(@ullable CharSequence str)569 private String getSequenceString(@Nullable CharSequence str) { 570 if (str == null) { 571 // A value of null retrieved from a StringPool indicates that retrieval of the 572 // string failed due to incremental installation. The presence of all the XmlBlock 573 // data is verified when it is created, so this exception must not be possible. 574 throw new IllegalStateException("Retrieving a string from the StringPool of an" 575 + " XmlBlock should never fail"); 576 } 577 return str.toString(); 578 } 579 close()580 public void close() { 581 synchronized (mBlock) { 582 if (mParseState != 0) { 583 nativeDestroyParseState(mParseState); 584 mParseState = 0; 585 mBlock.decOpenCountLocked(); 586 } 587 } 588 } 589 finalize()590 protected void finalize() throws Throwable { 591 close(); 592 } 593 594 @Nullable getPooledString(int id)595 /*package*/ final CharSequence getPooledString(int id) { 596 return mStrings.getSequence(id); 597 } 598 599 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 600 /*package*/ long mParseState; 601 @UnsupportedAppUsage 602 private final XmlBlock mBlock; 603 private boolean mStarted = false; 604 private boolean mDecNextDepth = false; 605 private int mDepth = 0; 606 private int mEventType = START_DOCUMENT; 607 } 608 finalize()609 protected void finalize() throws Throwable { 610 close(); 611 } 612 613 /** 614 * Create from an existing xml block native object. This is 615 * -extremely- dangerous -- only use it if you absolutely know what you 616 * are doing! The given native object must exist for the entire lifetime 617 * of this newly creating XmlBlock. 618 */ XmlBlock(@ullable AssetManager assets, long xmlBlock)619 XmlBlock(@Nullable AssetManager assets, long xmlBlock) { 620 mAssets = assets; 621 mNative = xmlBlock; 622 mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false); 623 } 624 625 private @Nullable final AssetManager mAssets; 626 private long mNative; // final, but gets reset on close 627 /*package*/ final StringBlock mStrings; 628 private boolean mOpen = true; 629 private int mOpenCount = 1; 630 nativeCreate(byte[] data, int offset, int size)631 private static final native long nativeCreate(byte[] data, 632 int offset, 633 int size); nativeGetStringBlock(long obj)634 private static final native long nativeGetStringBlock(long obj); nativeCreateParseState(long obj, int resId)635 private static final native long nativeCreateParseState(long obj, int resId); nativeDestroyParseState(long state)636 private static final native void nativeDestroyParseState(long state); nativeDestroy(long obj)637 private static final native void nativeDestroy(long obj); 638 639 // ----------- @FastNative ------------------ 640 641 @FastNative nativeGetAttributeIndex( long state, String namespace, String name)642 private static native int nativeGetAttributeIndex( 643 long state, String namespace, String name); 644 645 // ----------- @CriticalNative ------------------ 646 @CriticalNative nativeNext(long state)647 /*package*/ static final native int nativeNext(long state); 648 649 @CriticalNative nativeGetNamespace(long state)650 private static final native int nativeGetNamespace(long state); 651 652 @CriticalNative nativeGetName(long state)653 /*package*/ static final native int nativeGetName(long state); 654 655 @CriticalNative nativeGetText(long state)656 private static final native int nativeGetText(long state); 657 658 @CriticalNative nativeGetLineNumber(long state)659 private static final native int nativeGetLineNumber(long state); 660 661 @CriticalNative nativeGetAttributeCount(long state)662 private static final native int nativeGetAttributeCount(long state); 663 664 @CriticalNative nativeGetAttributeNamespace(long state, int idx)665 private static final native int nativeGetAttributeNamespace(long state, int idx); 666 667 @CriticalNative nativeGetAttributeName(long state, int idx)668 private static final native int nativeGetAttributeName(long state, int idx); 669 670 @CriticalNative nativeGetAttributeResource(long state, int idx)671 private static final native int nativeGetAttributeResource(long state, int idx); 672 673 @CriticalNative nativeGetAttributeDataType(long state, int idx)674 private static final native int nativeGetAttributeDataType(long state, int idx); 675 676 @CriticalNative nativeGetAttributeData(long state, int idx)677 private static final native int nativeGetAttributeData(long state, int idx); 678 679 @CriticalNative nativeGetAttributeStringValue(long state, int idx)680 private static final native int nativeGetAttributeStringValue(long state, int idx); 681 682 @CriticalNative nativeGetIdAttribute(long state)683 private static final native int nativeGetIdAttribute(long state); 684 685 @CriticalNative nativeGetClassAttribute(long state)686 private static final native int nativeGetClassAttribute(long state); 687 688 @CriticalNative nativeGetStyleAttribute(long state)689 private static final native int nativeGetStyleAttribute(long state); 690 691 @CriticalNative nativeGetSourceResId(long state)692 private static final native int nativeGetSourceResId(long state); 693 } 694