BridgeContext.java revision 4ccc4bd54f85d86818f61d728c6361d2003ddd8e
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 17package com.android.layoutlib.bridge.android; 18 19import com.android.ide.common.rendering.api.ILayoutPullParser; 20import com.android.ide.common.rendering.api.IProjectCallback; 21import com.android.ide.common.rendering.api.LayoutLog; 22import com.android.ide.common.rendering.api.RenderResources; 23import com.android.ide.common.rendering.api.ResourceReference; 24import com.android.ide.common.rendering.api.ResourceValue; 25import com.android.ide.common.rendering.api.StyleResourceValue; 26import com.android.layoutlib.bridge.Bridge; 27import com.android.layoutlib.bridge.BridgeConstants; 28import com.android.layoutlib.bridge.android.view.WindowManagerImpl; 29import com.android.layoutlib.bridge.impl.ParserFactory; 30import com.android.layoutlib.bridge.impl.Stack; 31import com.android.resources.ResourceType; 32import com.android.util.Pair; 33 34import org.xmlpull.v1.XmlPullParser; 35import org.xmlpull.v1.XmlPullParserException; 36 37import android.content.BroadcastReceiver; 38import android.content.ComponentName; 39import android.content.ContentResolver; 40import android.content.Context; 41import android.content.Intent; 42import android.content.IntentFilter; 43import android.content.IntentSender; 44import android.content.ServiceConnection; 45import android.content.SharedPreferences; 46import android.content.pm.ApplicationInfo; 47import android.content.pm.PackageManager; 48import android.content.res.AssetManager; 49import android.content.res.BridgeResources; 50import android.content.res.BridgeTypedArray; 51import android.content.res.Configuration; 52import android.content.res.Resources; 53import android.content.res.Resources.Theme; 54import android.content.res.TypedArray; 55import android.database.DatabaseErrorHandler; 56import android.database.sqlite.SQLiteDatabase; 57import android.database.sqlite.SQLiteDatabase.CursorFactory; 58import android.graphics.Bitmap; 59import android.graphics.drawable.Drawable; 60import android.net.Uri; 61import android.os.Bundle; 62import android.os.Handler; 63import android.os.Looper; 64import android.os.PowerManager; 65import android.os.UserHandle; 66import android.util.AttributeSet; 67import android.util.DisplayMetrics; 68import android.util.TypedValue; 69import android.view.BridgeInflater; 70import android.view.Display; 71import android.view.DisplayAdjustments; 72import android.view.View; 73import android.view.ViewGroup; 74import android.view.WindowManager; 75import android.view.textservice.TextServicesManager; 76 77import java.io.File; 78import java.io.FileInputStream; 79import java.io.FileNotFoundException; 80import java.io.FileOutputStream; 81import java.io.IOException; 82import java.io.InputStream; 83import java.util.ArrayList; 84import java.util.HashMap; 85import java.util.IdentityHashMap; 86import java.util.List; 87import java.util.Map; 88 89/** 90 * Custom implementation of Context/Activity to handle non compiled resources. 91 */ 92public final class BridgeContext extends Context { 93 94 private Resources mSystemResources; 95 private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>(); 96 private final Object mProjectKey; 97 private final DisplayMetrics mMetrics; 98 private final RenderResources mRenderResources; 99 private final Configuration mConfig; 100 private final ApplicationInfo mApplicationInfo; 101 private final IProjectCallback mProjectCallback; 102 private final WindowManager mWindowManager; 103 104 private Resources.Theme mTheme; 105 106 private final Map<Object, Map<String, String>> mDefaultPropMaps = 107 new IdentityHashMap<Object, Map<String,String>>(); 108 109 // maps for dynamically generated id representing style objects (StyleResourceValue) 110 private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap; 111 private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap; 112 private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style 113 114 // cache for TypedArray generated from IStyleResourceValue object 115 private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache; 116 private BridgeInflater mBridgeInflater; 117 118 private BridgeContentResolver mContentResolver; 119 120 private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>(); 121 122 /** 123 * @param projectKey An Object identifying the project. This is used for the cache mechanism. 124 * @param metrics the {@link DisplayMetrics}. 125 * @param renderResources the configured resources (both framework and projects) for this 126 * render. 127 * @param projectCallback 128 * @param config the Configuration object for this render. 129 * @param targetSdkVersion the targetSdkVersion of the application. 130 */ 131 public BridgeContext(Object projectKey, DisplayMetrics metrics, 132 RenderResources renderResources, 133 IProjectCallback projectCallback, 134 Configuration config, 135 int targetSdkVersion, 136 boolean hasRtlSupport) { 137 mProjectKey = projectKey; 138 mMetrics = metrics; 139 mProjectCallback = projectCallback; 140 141 mRenderResources = renderResources; 142 mConfig = config; 143 144 mApplicationInfo = new ApplicationInfo(); 145 mApplicationInfo.targetSdkVersion = targetSdkVersion; 146 if (hasRtlSupport) { 147 mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL; 148 } 149 150 mWindowManager = new WindowManagerImpl(mMetrics); 151 } 152 153 /** 154 * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its 155 * {@link DisplayMetrics}, {@link Configuration}, and {@link IProjectCallback}. 156 * 157 * @see #disposeResources() 158 */ 159 public void initResources() { 160 AssetManager assetManager = AssetManager.getSystem(); 161 162 mSystemResources = BridgeResources.initSystem( 163 this, 164 assetManager, 165 mMetrics, 166 mConfig, 167 mProjectCallback); 168 mTheme = mSystemResources.newTheme(); 169 } 170 171 /** 172 * Disposes the {@link Resources} singleton. 173 */ 174 public void disposeResources() { 175 BridgeResources.disposeSystem(); 176 } 177 178 public void setBridgeInflater(BridgeInflater inflater) { 179 mBridgeInflater = inflater; 180 } 181 182 public void addViewKey(View view, Object viewKey) { 183 mViewKeyMap.put(view, viewKey); 184 } 185 186 public Object getViewKey(View view) { 187 return mViewKeyMap.get(view); 188 } 189 190 public Object getProjectKey() { 191 return mProjectKey; 192 } 193 194 public DisplayMetrics getMetrics() { 195 return mMetrics; 196 } 197 198 public IProjectCallback getProjectCallback() { 199 return mProjectCallback; 200 } 201 202 public RenderResources getRenderResources() { 203 return mRenderResources; 204 } 205 206 public Map<String, String> getDefaultPropMap(Object key) { 207 return mDefaultPropMaps.get(key); 208 } 209 210 public Configuration getConfiguration() { 211 return mConfig; 212 } 213 214 /** 215 * Adds a parser to the stack. 216 * @param parser the parser to add. 217 */ 218 public void pushParser(BridgeXmlBlockParser parser) { 219 if (ParserFactory.LOG_PARSER) { 220 System.out.println("PUSH " + parser.getParser().toString()); 221 } 222 mParserStack.push(parser); 223 } 224 225 /** 226 * Removes the parser at the top of the stack 227 */ 228 public void popParser() { 229 BridgeXmlBlockParser parser = mParserStack.pop(); 230 if (ParserFactory.LOG_PARSER) { 231 System.out.println("POPD " + parser.getParser().toString()); 232 } 233 } 234 235 /** 236 * Returns the current parser at the top the of the stack. 237 * @return a parser or null. 238 */ 239 public BridgeXmlBlockParser getCurrentParser() { 240 return mParserStack.peek(); 241 } 242 243 /** 244 * Returns the previous parser. 245 * @return a parser or null if there isn't any previous parser 246 */ 247 public BridgeXmlBlockParser getPreviousParser() { 248 if (mParserStack.size() < 2) { 249 return null; 250 } 251 return mParserStack.get(mParserStack.size() - 2); 252 } 253 254 public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) { 255 Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid); 256 boolean isFrameworkRes = true; 257 if (resourceInfo == null) { 258 resourceInfo = mProjectCallback.resolveResourceId(resid); 259 isFrameworkRes = false; 260 } 261 262 if (resourceInfo == null) { 263 return false; 264 } 265 266 ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(), 267 isFrameworkRes); 268 if (resolveRefs) { 269 value = mRenderResources.resolveResValue(value); 270 } 271 272 // check if this is a style resource 273 if (value instanceof StyleResourceValue) { 274 // get the id that will represent this style. 275 outValue.resourceId = getDynamicIdByStyle((StyleResourceValue)value); 276 return true; 277 } 278 279 280 int a; 281 // if this is a framework value. 282 if (value.isFramework()) { 283 // look for idName in the android R classes. 284 // use 0 a default res value as it's not a valid id value. 285 a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); 286 } else { 287 // look for idName in the project R class. 288 // use 0 a default res value as it's not a valid id value. 289 a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); 290 } 291 292 if (a != 0) { 293 outValue.resourceId = a; 294 return true; 295 } 296 297 return false; 298 } 299 300 301 public ResourceReference resolveId(int id) { 302 // first get the String related to this id in the framework 303 Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); 304 305 if (resourceInfo != null) { 306 return new ResourceReference(resourceInfo.getSecond(), true); 307 } 308 309 // didn't find a match in the framework? look in the project. 310 if (mProjectCallback != null) { 311 resourceInfo = mProjectCallback.resolveResourceId(id); 312 313 if (resourceInfo != null) { 314 return new ResourceReference(resourceInfo.getSecond(), false); 315 } 316 } 317 318 return null; 319 } 320 321 public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent, 322 boolean attachToRoot, boolean skipCallbackParser) { 323 boolean isPlatformLayout = resource.isFramework(); 324 325 if (isPlatformLayout == false && skipCallbackParser == false) { 326 // check if the project callback can provide us with a custom parser. 327 ILayoutPullParser parser = getParser(resource); 328 329 if (parser != null) { 330 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, 331 this, resource.isFramework()); 332 try { 333 pushParser(blockParser); 334 return Pair.of( 335 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 336 true); 337 } finally { 338 popParser(); 339 } 340 } 341 } 342 343 ResourceValue resValue; 344 if (resource instanceof ResourceValue) { 345 resValue = (ResourceValue) resource; 346 } else { 347 if (isPlatformLayout) { 348 resValue = mRenderResources.getFrameworkResource(ResourceType.LAYOUT, 349 resource.getName()); 350 } else { 351 resValue = mRenderResources.getProjectResource(ResourceType.LAYOUT, 352 resource.getName()); 353 } 354 } 355 356 if (resValue != null) { 357 358 File xml = new File(resValue.getValue()); 359 if (xml.isFile()) { 360 // we need to create a pull parser around the layout XML file, and then 361 // give that to our XmlBlockParser 362 try { 363 XmlPullParser parser = ParserFactory.create(xml); 364 365 // set the resource ref to have correct view cookies 366 mBridgeInflater.setResourceReference(resource); 367 368 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, 369 this, resource.isFramework()); 370 try { 371 pushParser(blockParser); 372 return Pair.of( 373 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 374 false); 375 } finally { 376 popParser(); 377 } 378 } catch (XmlPullParserException e) { 379 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 380 "Failed to configure parser for " + xml, e, null /*data*/); 381 // we'll return null below. 382 } catch (FileNotFoundException e) { 383 // this shouldn't happen since we check above. 384 } finally { 385 mBridgeInflater.setResourceReference(null); 386 } 387 } else { 388 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 389 String.format("File %s is missing!", xml), null); 390 } 391 } else { 392 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 393 String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "", 394 resource.getName()), null); 395 } 396 397 return Pair.of(null, false); 398 } 399 400 @SuppressWarnings("deprecation") 401 private ILayoutPullParser getParser(ResourceReference resource) { 402 ILayoutPullParser parser; 403 if (resource instanceof ResourceValue) { 404 parser = mProjectCallback.getParser((ResourceValue) resource); 405 } else { 406 parser = mProjectCallback.getParser(resource.getName()); 407 } 408 return parser; 409 } 410 411 // ------------ Context methods 412 413 @Override 414 public Resources getResources() { 415 return mSystemResources; 416 } 417 418 @Override 419 public Theme getTheme() { 420 return mTheme; 421 } 422 423 @Override 424 public ClassLoader getClassLoader() { 425 return this.getClass().getClassLoader(); 426 } 427 428 @Override 429 public Object getSystemService(String service) { 430 if (LAYOUT_INFLATER_SERVICE.equals(service)) { 431 return mBridgeInflater; 432 } 433 434 if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) { 435 // we need to return a valid service to avoid NPE 436 return TextServicesManager.getInstance(); 437 } 438 439 if (WINDOW_SERVICE.equals(service)) { 440 return mWindowManager; 441 } 442 443 // needed by SearchView 444 if (INPUT_METHOD_SERVICE.equals(service)) { 445 return null; 446 } 447 448 if (POWER_SERVICE.equals(service)) { 449 return new PowerManager(this, new BridgePowerManager(), new Handler()); 450 } 451 452 throw new UnsupportedOperationException("Unsupported Service: " + service); 453 } 454 455 456 @Override 457 public final TypedArray obtainStyledAttributes(int[] attrs) { 458 return createStyleBasedTypedArray(mRenderResources.getCurrentTheme(), attrs); 459 } 460 461 @Override 462 public final TypedArray obtainStyledAttributes(int resid, int[] attrs) 463 throws Resources.NotFoundException { 464 // get the StyleResourceValue based on the resId; 465 StyleResourceValue style = getStyleByDynamicId(resid); 466 467 if (style == null) { 468 throw new Resources.NotFoundException(); 469 } 470 471 if (mTypedArrayCache == null) { 472 mTypedArrayCache = new HashMap<int[], Map<Integer,TypedArray>>(); 473 474 Map<Integer, TypedArray> map = new HashMap<Integer, TypedArray>(); 475 mTypedArrayCache.put(attrs, map); 476 477 BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs); 478 map.put(resid, ta); 479 480 return ta; 481 } 482 483 // get the 2nd map 484 Map<Integer, TypedArray> map = mTypedArrayCache.get(attrs); 485 if (map == null) { 486 map = new HashMap<Integer, TypedArray>(); 487 mTypedArrayCache.put(attrs, map); 488 } 489 490 // get the array from the 2nd map 491 TypedArray ta = map.get(resid); 492 493 if (ta == null) { 494 ta = createStyleBasedTypedArray(style, attrs); 495 map.put(resid, ta); 496 } 497 498 return ta; 499 } 500 501 @Override 502 public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { 503 return obtainStyledAttributes(set, attrs, 0, 0); 504 } 505 506 @Override 507 public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, 508 int defStyleAttr, int defStyleRes) { 509 510 Map<String, String> defaultPropMap = null; 511 boolean isPlatformFile = true; 512 513 // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java 514 if (set instanceof BridgeXmlBlockParser) { 515 BridgeXmlBlockParser parser = null; 516 parser = (BridgeXmlBlockParser)set; 517 518 isPlatformFile = parser.isPlatformFile(); 519 520 Object key = parser.getViewCookie(); 521 if (key != null) { 522 defaultPropMap = mDefaultPropMaps.get(key); 523 if (defaultPropMap == null) { 524 defaultPropMap = new HashMap<String, String>(); 525 mDefaultPropMaps.put(key, defaultPropMap); 526 } 527 } 528 529 } else if (set instanceof BridgeLayoutParamsMapAttributes) { 530 // this is only for temp layout params generated dynamically, so this is never 531 // platform content. 532 isPlatformFile = false; 533 } else if (set != null) { // null parser is ok 534 // really this should not be happening since its instantiated in Bridge 535 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 536 "Parser is not a BridgeXmlBlockParser!", null /*data*/); 537 return null; 538 } 539 540 List<Pair<String, Boolean>> attributeList = searchAttrs(attrs); 541 542 BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, 543 isPlatformFile); 544 545 // look for a custom style. 546 String customStyle = null; 547 if (set != null) { 548 customStyle = set.getAttributeValue(null /* namespace*/, "style"); 549 } 550 551 StyleResourceValue customStyleValues = null; 552 if (customStyle != null) { 553 ResourceValue item = mRenderResources.findResValue(customStyle, 554 false /*forceFrameworkOnly*/); 555 556 // resolve it in case it links to something else 557 item = mRenderResources.resolveResValue(item); 558 559 if (item instanceof StyleResourceValue) { 560 customStyleValues = (StyleResourceValue)item; 561 } 562 } 563 564 // resolve the defStyleAttr value into a IStyleResourceValue 565 StyleResourceValue defStyleValues = null; 566 567 if (defStyleAttr != 0) { 568 // get the name from the int. 569 Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr); 570 571 if (defaultPropMap != null) { 572 String defStyleName = defStyleAttribute.getFirst(); 573 if (defStyleAttribute.getSecond()) { 574 defStyleName = "android:" + defStyleName; 575 } 576 defaultPropMap.put("style", defStyleName); 577 } 578 579 // look for the style in the current theme, and its parent: 580 ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute.getFirst(), 581 defStyleAttribute.getSecond()); 582 583 if (item != null) { 584 // item is a reference to a style entry. Search for it. 585 item = mRenderResources.findResValue(item.getValue(), 586 false /*forceFrameworkOnly*/); 587 588 if (item instanceof StyleResourceValue) { 589 defStyleValues = (StyleResourceValue)item; 590 } 591 } else { 592 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, 593 String.format( 594 "Failed to find style '%s' in current theme", 595 defStyleAttribute.getFirst()), 596 null /*data*/); 597 } 598 } else if (defStyleRes != 0) { 599 boolean isFrameworkRes = true; 600 Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes); 601 if (value == null) { 602 value = mProjectCallback.resolveResourceId(defStyleRes); 603 isFrameworkRes = false; 604 } 605 606 if (value != null) { 607 if ((value.getFirst() == ResourceType.STYLE) 608 || (value.getFirst() == ResourceType.ATTR)) { 609 // look for the style in the current theme, and its parent: 610 ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(), 611 isFrameworkRes); 612 if (item != null) { 613 if (item instanceof StyleResourceValue) { 614 if (defaultPropMap != null) { 615 defaultPropMap.put("style", item.getName()); 616 } 617 618 defStyleValues = (StyleResourceValue)item; 619 } 620 } else { 621 Bridge.getLog().error(null, 622 String.format( 623 "Style with id 0x%x (resolved to '%s') does not exist.", 624 defStyleRes, value.getSecond()), 625 null /*data*/); 626 } 627 } else { 628 Bridge.getLog().error(null, 629 String.format( 630 "Resouce id 0x%x is not of type STYLE (instead %s)", 631 defStyleRes, value.getFirst().toString()), 632 null /*data*/); 633 } 634 } else { 635 Bridge.getLog().error(null, 636 String.format( 637 "Failed to find style with id 0x%x in current theme", 638 defStyleRes), 639 null /*data*/); 640 } 641 } 642 643 String appNamespace = mProjectCallback.getNamespace(); 644 645 if (attributeList != null) { 646 for (int index = 0 ; index < attributeList.size() ; index++) { 647 Pair<String, Boolean> attribute = attributeList.get(index); 648 649 if (attribute == null) { 650 continue; 651 } 652 653 String attrName = attribute.getFirst(); 654 boolean frameworkAttr = attribute.getSecond().booleanValue(); 655 String value = null; 656 if (set != null) { 657 value = set.getAttributeValue( 658 frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, 659 attrName); 660 661 // if this is an app attribute, and the first get fails, try with the 662 // new res-auto namespace as well 663 if (frameworkAttr == false && value == null) { 664 value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName); 665 } 666 } 667 668 // if there's no direct value for this attribute in the XML, we look for default 669 // values in the widget defStyle, and then in the theme. 670 if (value == null) { 671 ResourceValue resValue = null; 672 673 // look for the value in the custom style first (and its parent if needed) 674 if (customStyleValues != null) { 675 resValue = mRenderResources.findItemInStyle(customStyleValues, 676 attrName, frameworkAttr); 677 } 678 679 // then look for the value in the default Style (and its parent if needed) 680 if (resValue == null && defStyleValues != null) { 681 resValue = mRenderResources.findItemInStyle(defStyleValues, 682 attrName, frameworkAttr); 683 } 684 685 // if the item is not present in the defStyle, we look in the main theme (and 686 // its parent themes) 687 if (resValue == null) { 688 resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr); 689 } 690 691 // if we found a value, we make sure this doesn't reference another value. 692 // So we resolve it. 693 if (resValue != null) { 694 // put the first default value, before the resolution. 695 if (defaultPropMap != null) { 696 defaultPropMap.put(attrName, resValue.getValue()); 697 } 698 699 resValue = mRenderResources.resolveResValue(resValue); 700 } 701 702 ta.bridgeSetValue(index, attrName, frameworkAttr, resValue); 703 } else { 704 // there is a value in the XML, but we need to resolve it in case it's 705 // referencing another resource or a theme value. 706 ta.bridgeSetValue(index, attrName, frameworkAttr, 707 mRenderResources.resolveValue(null, attrName, value, isPlatformFile)); 708 } 709 } 710 } 711 712 ta.sealArray(); 713 714 return ta; 715 } 716 717 @Override 718 public Looper getMainLooper() { 719 return Looper.myLooper(); 720 } 721 722 723 // ------------- private new methods 724 725 /** 726 * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the 727 * values found in the given style. 728 * @see #obtainStyledAttributes(int, int[]) 729 */ 730 private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs) 731 throws Resources.NotFoundException { 732 733 List<Pair<String, Boolean>> attributes = searchAttrs(attrs); 734 735 BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, 736 false); 737 738 // for each attribute, get its name so that we can search it in the style 739 for (int i = 0 ; i < attrs.length ; i++) { 740 Pair<String, Boolean> attribute = attributes.get(i); 741 742 if (attribute != null) { 743 // look for the value in the given style 744 ResourceValue resValue = mRenderResources.findItemInStyle(style, 745 attribute.getFirst(), attribute.getSecond()); 746 747 if (resValue != null) { 748 // resolve it to make sure there are no references left. 749 ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(), 750 mRenderResources.resolveResValue(resValue)); 751 } 752 } 753 } 754 755 ta.sealArray(); 756 757 return ta; 758 } 759 760 761 /** 762 * The input int[] attrs is a list of attributes. The returns a list of information about 763 * each attributes. The information is (name, isFramework) 764 * <p/> 765 * 766 * @param attrs An attribute array reference given to obtainStyledAttributes. 767 * @return List of attribute information. 768 */ 769 private List<Pair<String, Boolean>> searchAttrs(int[] attrs) { 770 List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length); 771 772 // for each attribute, get its name so that we can search it in the style 773 for (int i = 0 ; i < attrs.length ; i++) { 774 Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]); 775 boolean isFramework = false; 776 if (resolvedResource != null) { 777 isFramework = true; 778 } else { 779 resolvedResource = mProjectCallback.resolveResourceId(attrs[i]); 780 } 781 782 if (resolvedResource != null) { 783 results.add(Pair.of(resolvedResource.getSecond(), isFramework)); 784 } else { 785 results.add(null); 786 } 787 } 788 789 return results; 790 } 791 792 /** 793 * Searches for the attribute referenced by its internal id. 794 * 795 * @param attr An attribute reference given to obtainStyledAttributes such as defStyle. 796 * @return A (name, isFramework) pair describing the attribute if found. Returns null 797 * if nothing is found. 798 */ 799 public Pair<String, Boolean> searchAttr(int attr) { 800 Pair<ResourceType, String> info = Bridge.resolveResourceId(attr); 801 if (info != null) { 802 return Pair.of(info.getSecond(), Boolean.TRUE); 803 } 804 805 info = mProjectCallback.resolveResourceId(attr); 806 if (info != null) { 807 return Pair.of(info.getSecond(), Boolean.FALSE); 808 } 809 810 return null; 811 } 812 813 public int getDynamicIdByStyle(StyleResourceValue resValue) { 814 if (mDynamicIdToStyleMap == null) { 815 // create the maps. 816 mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>(); 817 mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>(); 818 } 819 820 // look for an existing id 821 Integer id = mStyleToDynamicIdMap.get(resValue); 822 823 if (id == null) { 824 // generate a new id 825 id = Integer.valueOf(++mDynamicIdGenerator); 826 827 // and add it to the maps. 828 mDynamicIdToStyleMap.put(id, resValue); 829 mStyleToDynamicIdMap.put(resValue, id); 830 } 831 832 return id; 833 } 834 835 private StyleResourceValue getStyleByDynamicId(int i) { 836 if (mDynamicIdToStyleMap != null) { 837 return mDynamicIdToStyleMap.get(i); 838 } 839 840 return null; 841 } 842 843 public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) { 844 Integer value = Bridge.getResourceId(resType, resName); 845 if (value != null) { 846 return value.intValue(); 847 } 848 849 return defValue; 850 } 851 852 public int getProjectResourceValue(ResourceType resType, String resName, int defValue) { 853 if (mProjectCallback != null) { 854 Integer value = mProjectCallback.getResourceId(resType, resName); 855 if (value != null) { 856 return value.intValue(); 857 } 858 } 859 860 return defValue; 861 } 862 863 //------------ NOT OVERRIDEN -------------------- 864 865 @Override 866 public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) { 867 // pass 868 return false; 869 } 870 871 @Override 872 public int checkCallingOrSelfPermission(String arg0) { 873 // pass 874 return 0; 875 } 876 877 @Override 878 public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) { 879 // pass 880 return 0; 881 } 882 883 @Override 884 public int checkCallingPermission(String arg0) { 885 // pass 886 return 0; 887 } 888 889 @Override 890 public int checkCallingUriPermission(Uri arg0, int arg1) { 891 // pass 892 return 0; 893 } 894 895 @Override 896 public int checkPermission(String arg0, int arg1, int arg2) { 897 // pass 898 return 0; 899 } 900 901 @Override 902 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) { 903 // pass 904 return 0; 905 } 906 907 @Override 908 public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, 909 int arg4, int arg5) { 910 // pass 911 return 0; 912 } 913 914 @Override 915 public void clearWallpaper() { 916 // pass 917 918 } 919 920 @Override 921 public Context createPackageContext(String arg0, int arg1) { 922 // pass 923 return null; 924 } 925 926 @Override 927 public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) { 928 // pass 929 return null; 930 } 931 932 @Override 933 public Context createConfigurationContext(Configuration overrideConfiguration) { 934 // pass 935 return null; 936 } 937 938 @Override 939 public Context createDisplayContext(Display display) { 940 // pass 941 return null; 942 } 943 944 @Override 945 public String[] databaseList() { 946 // pass 947 return null; 948 } 949 950 @Override 951 public boolean deleteDatabase(String arg0) { 952 // pass 953 return false; 954 } 955 956 @Override 957 public boolean deleteFile(String arg0) { 958 // pass 959 return false; 960 } 961 962 @Override 963 public void enforceCallingOrSelfPermission(String arg0, String arg1) { 964 // pass 965 966 } 967 968 @Override 969 public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, 970 String arg2) { 971 // pass 972 973 } 974 975 @Override 976 public void enforceCallingPermission(String arg0, String arg1) { 977 // pass 978 979 } 980 981 @Override 982 public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { 983 // pass 984 985 } 986 987 @Override 988 public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { 989 // pass 990 991 } 992 993 @Override 994 public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, 995 String arg4) { 996 // pass 997 998 } 999 1000 @Override 1001 public void enforceUriPermission(Uri arg0, String arg1, String arg2, 1002 int arg3, int arg4, int arg5, String arg6) { 1003 // pass 1004 1005 } 1006 1007 @Override 1008 public String[] fileList() { 1009 // pass 1010 return null; 1011 } 1012 1013 @Override 1014 public AssetManager getAssets() { 1015 // pass 1016 return null; 1017 } 1018 1019 @Override 1020 public File getCacheDir() { 1021 // pass 1022 return null; 1023 } 1024 1025 @Override 1026 public File getExternalCacheDir() { 1027 // pass 1028 return null; 1029 } 1030 1031 @Override 1032 public ContentResolver getContentResolver() { 1033 if (mContentResolver == null) { 1034 mContentResolver = new BridgeContentResolver(this); 1035 } 1036 return mContentResolver; 1037 } 1038 1039 @Override 1040 public File getDatabasePath(String arg0) { 1041 // pass 1042 return null; 1043 } 1044 1045 @Override 1046 public File getDir(String arg0, int arg1) { 1047 // pass 1048 return null; 1049 } 1050 1051 @Override 1052 public File getFileStreamPath(String arg0) { 1053 // pass 1054 return null; 1055 } 1056 1057 @Override 1058 public File getFilesDir() { 1059 // pass 1060 return null; 1061 } 1062 1063 @Override 1064 public File getExternalFilesDir(String type) { 1065 // pass 1066 return null; 1067 } 1068 1069 @Override 1070 public String getPackageCodePath() { 1071 // pass 1072 return null; 1073 } 1074 1075 @Override 1076 public PackageManager getPackageManager() { 1077 // pass 1078 return null; 1079 } 1080 1081 @Override 1082 public String getPackageName() { 1083 // pass 1084 return null; 1085 } 1086 1087 @Override 1088 public String getBasePackageName() { 1089 // pass 1090 return null; 1091 } 1092 1093 @Override 1094 public String getOpPackageName() { 1095 // pass 1096 return null; 1097 } 1098 1099 @Override 1100 public ApplicationInfo getApplicationInfo() { 1101 return mApplicationInfo; 1102 } 1103 1104 @Override 1105 public String getPackageResourcePath() { 1106 // pass 1107 return null; 1108 } 1109 1110 @Override 1111 public File getSharedPrefsFile(String name) { 1112 // pass 1113 return null; 1114 } 1115 1116 @Override 1117 public SharedPreferences getSharedPreferences(String arg0, int arg1) { 1118 // pass 1119 return null; 1120 } 1121 1122 @Override 1123 public Drawable getWallpaper() { 1124 // pass 1125 return null; 1126 } 1127 1128 @Override 1129 public int getWallpaperDesiredMinimumWidth() { 1130 return -1; 1131 } 1132 1133 @Override 1134 public int getWallpaperDesiredMinimumHeight() { 1135 return -1; 1136 } 1137 1138 @Override 1139 public void grantUriPermission(String arg0, Uri arg1, int arg2) { 1140 // pass 1141 1142 } 1143 1144 @Override 1145 public FileInputStream openFileInput(String arg0) throws FileNotFoundException { 1146 // pass 1147 return null; 1148 } 1149 1150 @Override 1151 public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException { 1152 // pass 1153 return null; 1154 } 1155 1156 @Override 1157 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) { 1158 // pass 1159 return null; 1160 } 1161 1162 @Override 1163 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, 1164 CursorFactory arg2, DatabaseErrorHandler arg3) { 1165 // pass 1166 return null; 1167 } 1168 1169 @Override 1170 public Drawable peekWallpaper() { 1171 // pass 1172 return null; 1173 } 1174 1175 @Override 1176 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) { 1177 // pass 1178 return null; 1179 } 1180 1181 @Override 1182 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, 1183 String arg2, Handler arg3) { 1184 // pass 1185 return null; 1186 } 1187 1188 @Override 1189 public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, 1190 IntentFilter arg1, String arg2, Handler arg3) { 1191 // pass 1192 return null; 1193 } 1194 1195 @Override 1196 public void removeStickyBroadcast(Intent arg0) { 1197 // pass 1198 1199 } 1200 1201 @Override 1202 public void revokeUriPermission(Uri arg0, int arg1) { 1203 // pass 1204 1205 } 1206 1207 @Override 1208 public void sendBroadcast(Intent arg0) { 1209 // pass 1210 1211 } 1212 1213 @Override 1214 public void sendBroadcast(Intent arg0, String arg1) { 1215 // pass 1216 1217 } 1218 1219 @Override 1220 public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { 1221 // pass 1222 } 1223 1224 @Override 1225 public void sendOrderedBroadcast(Intent arg0, String arg1) { 1226 // pass 1227 1228 } 1229 1230 @Override 1231 public void sendOrderedBroadcast(Intent arg0, String arg1, 1232 BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, 1233 Bundle arg6) { 1234 // pass 1235 1236 } 1237 1238 @Override 1239 public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, 1240 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 1241 String initialData, Bundle initialExtras) { 1242 // pass 1243 } 1244 1245 @Override 1246 public void sendBroadcastAsUser(Intent intent, UserHandle user) { 1247 // pass 1248 } 1249 1250 @Override 1251 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1252 String receiverPermission) { 1253 // pass 1254 } 1255 1256 @Override 1257 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1258 String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, 1259 int initialCode, String initialData, Bundle initialExtras) { 1260 // pass 1261 } 1262 1263 @Override 1264 public void sendStickyBroadcast(Intent arg0) { 1265 // pass 1266 1267 } 1268 1269 @Override 1270 public void sendStickyOrderedBroadcast(Intent intent, 1271 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, 1272 Bundle initialExtras) { 1273 // pass 1274 } 1275 1276 @Override 1277 public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { 1278 // pass 1279 } 1280 1281 @Override 1282 public void sendStickyOrderedBroadcastAsUser(Intent intent, 1283 UserHandle user, BroadcastReceiver resultReceiver, 1284 Handler scheduler, int initialCode, String initialData, 1285 Bundle initialExtras) { 1286 // pass 1287 } 1288 1289 @Override 1290 public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { 1291 // pass 1292 } 1293 1294 @Override 1295 public void setTheme(int arg0) { 1296 // pass 1297 1298 } 1299 1300 @Override 1301 public void setWallpaper(Bitmap arg0) throws IOException { 1302 // pass 1303 1304 } 1305 1306 @Override 1307 public void setWallpaper(InputStream arg0) throws IOException { 1308 // pass 1309 1310 } 1311 1312 @Override 1313 public void startActivity(Intent arg0) { 1314 // pass 1315 } 1316 1317 @Override 1318 public void startActivity(Intent arg0, Bundle arg1) { 1319 // pass 1320 } 1321 1322 @Override 1323 public void startIntentSender(IntentSender intent, 1324 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) 1325 throws IntentSender.SendIntentException { 1326 // pass 1327 } 1328 1329 @Override 1330 public void startIntentSender(IntentSender intent, 1331 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, 1332 Bundle options) throws IntentSender.SendIntentException { 1333 // pass 1334 } 1335 1336 @Override 1337 public boolean startInstrumentation(ComponentName arg0, String arg1, 1338 Bundle arg2) { 1339 // pass 1340 return false; 1341 } 1342 1343 @Override 1344 public ComponentName startService(Intent arg0) { 1345 // pass 1346 return null; 1347 } 1348 1349 @Override 1350 public boolean stopService(Intent arg0) { 1351 // pass 1352 return false; 1353 } 1354 1355 @Override 1356 public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) { 1357 // pass 1358 return null; 1359 } 1360 1361 @Override 1362 public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { 1363 // pass 1364 return false; 1365 } 1366 1367 @Override 1368 public void unbindService(ServiceConnection arg0) { 1369 // pass 1370 1371 } 1372 1373 @Override 1374 public void unregisterReceiver(BroadcastReceiver arg0) { 1375 // pass 1376 1377 } 1378 1379 @Override 1380 public Context getApplicationContext() { 1381 return this; 1382 } 1383 1384 @Override 1385 public void startActivities(Intent[] arg0) { 1386 // pass 1387 1388 } 1389 1390 @Override 1391 public void startActivities(Intent[] arg0, Bundle arg1) { 1392 // pass 1393 1394 } 1395 1396 @Override 1397 public boolean isRestricted() { 1398 return false; 1399 } 1400 1401 @Override 1402 public File getObbDir() { 1403 Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null); 1404 return null; 1405 } 1406 1407 @Override 1408 public DisplayAdjustments getDisplayAdjustments(int displayId) { 1409 // pass 1410 return null; 1411 } 1412 1413 /** 1414 * @hide 1415 */ 1416 @Override 1417 public int getUserId() { 1418 return 0; // not used 1419 } 1420 1421 @Override 1422 public File[] getExternalFilesDirs(String type) { 1423 // pass 1424 return new File[0]; 1425 } 1426 1427 @Override 1428 public File[] getObbDirs() { 1429 // pass 1430 return new File[0]; 1431 } 1432 1433 @Override 1434 public File[] getExternalCacheDirs() { 1435 // pass 1436 return new File[0]; 1437 } 1438} 1439