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