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