/** This is called when the native library are ready. */ public void onNativeLibraryReady( WindowAndroid windowAndroid, TabContentManager tabContentManager) { assert mLayerTitleCache == null : "Should be called once"; if (DeviceClassManager.enableLayerDecorationCache()) { mLayerTitleCache = new LayerTitleCache(getContext()); } mCompositorView.initNativeCompositor( SysUtils.isLowEndDevice(), windowAndroid, mLayerTitleCache, tabContentManager); if (mLayerTitleCache != null) { mLayerTitleCache.setResourceManager(getResourceManager()); } if (mControlContainer != null) { mCompositorView .getResourceManager() .getDynamicResourceLoader() .registerResource(R.id.control_container, mControlContainer.getToolbarResourceAdapter()); ViewResourceAdapter progressAdapter = mControlContainer.getProgressResourceAdapter(); if (progressAdapter != null) { mCompositorView .getResourceManager() .getDynamicResourceLoader() .registerResource(R.id.progress, progressAdapter); } } }
private void startModerateBindingManagementIfNeeded() { // Moderate binding doesn't apply to low end devices. if (SysUtils.isLowEndDevice()) return; boolean moderateBindingTillBackgrounded = FieldTrialList.findFullName("ModerateBindingOnBackgroundTabCreation").equals("Enabled"); ChildProcessLauncher.startModerateBindingManagement( mAppContext, moderateBindingTillBackgrounded); }
/** * The {@link DeviceClassManager} constructor should be self contained and rely on system * information and command line flags. */ private DeviceClassManager() { // Device based configurations. if (SysUtils.isLowEndDevice()) { mEnableSnapshots = false; mEnableLayerDecorationCache = true; mEnableAccessibilityLayout = true; mEnableAnimations = false; mEnablePrerendering = false; mEnableToolbarSwipe = false; mDisableDomainReliability = true; } else { mEnableSnapshots = true; mEnableLayerDecorationCache = true; mEnableAccessibilityLayout = false; mEnableAnimations = true; mEnablePrerendering = true; mEnableToolbarSwipe = true; mDisableDomainReliability = false; } if (DeviceFormFactor.isTablet(ApplicationStatus.getApplicationContext())) { mEnableAccessibilityLayout = false; } // Flag based configurations. CommandLine commandLine = CommandLine.getInstance(); mEnableAccessibilityLayout |= commandLine.hasSwitch(ChromeSwitches.ENABLE_ACCESSIBILITY_TAB_SWITCHER); mEnableFullscreen = !commandLine.hasSwitch(ChromeSwitches.DISABLE_FULLSCREEN); mEnableUndo = commandLine.hasSwitch(ChromeSwitches.ENABLE_HIGH_END_UI_UNDO); mEnableToolbarSwipeInDocumentMode = commandLine.hasSwitch(ChromeSwitches.ENABLE_TOOLBAR_SWIPE_IN_DOCUMENT_MODE); // Related features. if (mEnableAccessibilityLayout) { mEnableAnimations = false; } if (SysUtils.isLowEndDevice() || mEnableAccessibilityLayout) { mEnableUndo = true; } }
// Used internally to initialize the linker's static data. Assume lock is held. private static void ensureInitializedLocked() { assert Thread.holdsLock(Linker.class); if (!sInitialized) { sRelroSharingSupported = false; if (NativeLibraries.USE_LINKER) { if (DEBUG) Log.i(TAG, "Loading lib" + TAG + ".so"); try { System.loadLibrary(TAG); } catch (UnsatisfiedLinkError e) { // In a component build, the ".cr" suffix is added to each library name. System.loadLibrary(TAG + ".cr"); } sRelroSharingSupported = nativeCanUseSharedRelro(); if (!sRelroSharingSupported) Log.w(TAG, "This system cannot safely share RELRO sections"); else { if (DEBUG) Log.i(TAG, "This system supports safe shared RELRO sections"); } if (sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT) { sMemoryDeviceConfig = SysUtils.isLowEndDevice() ? MEMORY_DEVICE_CONFIG_LOW : MEMORY_DEVICE_CONFIG_NORMAL; } switch (BROWSER_SHARED_RELRO_CONFIG) { case BROWSER_SHARED_RELRO_CONFIG_NEVER: sBrowserUsesSharedRelro = false; break; case BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY: sBrowserUsesSharedRelro = (sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW); if (sBrowserUsesSharedRelro) Log.w(TAG, "Low-memory device: shared RELROs used in all processes"); break; case BROWSER_SHARED_RELRO_CONFIG_ALWAYS: Log.w(TAG, "Beware: shared RELROs used in all processes!"); sBrowserUsesSharedRelro = true; break; default: assert false : "Unreached"; break; } } else { if (DEBUG) Log.i(TAG, "Linker disabled"); } if (!sRelroSharingSupported) { // Sanity. sBrowserUsesSharedRelro = false; sWaitForSharedRelros = false; } sInitialized = true; } }
/** * Creates and shows the app menu anchored to the specified view. * * @param context The context of the AppMenu (ensure the proper theme is set on this context). * @param anchorView The anchor {@link View} of the {@link ListPopupWindow}. * @param isByPermanentButton Whether or not permanent hardware button triggered it. (oppose to * software button or keyboard). * @param screenRotation Current device screen rotation. * @param visibleDisplayFrame The display area rect in which AppMenu is supposed to fit in. * @param screenHeight Current device screen height. * @param footerResourceId The resource id for a view to add to the end of the menu list. Can be 0 * if no such view is required. */ void show( Context context, View anchorView, boolean isByPermanentButton, int screenRotation, Rect visibleDisplayFrame, int screenHeight, int footerResourceId) { mPopup = new ListPopupWindow(context, null, android.R.attr.popupMenuStyle); mPopup.setModal(true); mPopup.setAnchorView(anchorView); mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); int footerHeight = 0; if (footerResourceId != 0) { mPopup.setPromptPosition(ListPopupWindow.POSITION_PROMPT_BELOW); View promptView = LayoutInflater.from(context).inflate(footerResourceId, null); mPopup.setPromptView(promptView); int measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); promptView.measure(measureSpec, measureSpec); footerHeight = promptView.getMeasuredHeight(); } mPopup.setOnDismissListener( new OnDismissListener() { @Override public void onDismiss() { if (mPopup.getAnchorView() instanceof ImageButton) { ((ImageButton) mPopup.getAnchorView()).setSelected(false); } if (mMenuItemEnterAnimator != null) mMenuItemEnterAnimator.cancel(); mHandler.appMenuDismissed(); mHandler.onMenuVisibilityChanged(false); } }); // Some OEMs don't actually let us change the background... but they still return the // padding of the new background, which breaks the menu height. If we still have a // drawable here even though our style says @null we should use this padding instead... Drawable originalBgDrawable = mPopup.getBackground(); // Need to explicitly set the background here. Relying on it being set in the style caused // an incorrectly drawn background. if (isByPermanentButton) { mPopup.setBackgroundDrawable( ApiCompatibilityUtils.getDrawable(context.getResources(), R.drawable.menu_bg)); } else { mPopup.setBackgroundDrawable( ApiCompatibilityUtils.getDrawable(context.getResources(), R.drawable.edge_menu_bg)); mPopup.setAnimationStyle(R.style.OverflowMenuAnim); } // Turn off window animations for low end devices, and on Android M, which has built-in menu // animations. if (SysUtils.isLowEndDevice() || Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mPopup.setAnimationStyle(0); } Rect bgPadding = new Rect(); mPopup.getBackground().getPadding(bgPadding); int popupWidth = context.getResources().getDimensionPixelSize(R.dimen.menu_width) + bgPadding.left + bgPadding.right; mPopup.setWidth(popupWidth); mCurrentScreenRotation = screenRotation; mIsByPermanentButton = isByPermanentButton; // Extract visible items from the Menu. int numItems = mMenu.size(); List<MenuItem> menuItems = new ArrayList<MenuItem>(); for (int i = 0; i < numItems; ++i) { MenuItem item = mMenu.getItem(i); if (item.isVisible()) { menuItems.add(item); } } Rect sizingPadding = new Rect(bgPadding); if (isByPermanentButton && originalBgDrawable != null) { Rect originalPadding = new Rect(); originalBgDrawable.getPadding(originalPadding); sizingPadding.top = originalPadding.top; sizingPadding.bottom = originalPadding.bottom; } // A List adapter for visible items in the Menu. The first row is added as a header to the // list view. mAdapter = new AppMenuAdapter(this, menuItems, LayoutInflater.from(context)); mPopup.setAdapter(mAdapter); setMenuHeight(menuItems.size(), visibleDisplayFrame, screenHeight, sizingPadding, footerHeight); setPopupOffset(mPopup, mCurrentScreenRotation, visibleDisplayFrame, sizingPadding); mPopup.setOnItemClickListener(this); mPopup.show(); mPopup.getListView().setItemsCanFocus(true); mPopup.getListView().setOnKeyListener(this); mHandler.onMenuVisibilityChanged(true); if (mVerticalFadeDistance > 0) { mPopup.getListView().setVerticalFadingEdgeEnabled(true); mPopup.getListView().setFadingEdgeLength(mVerticalFadeDistance); } // Don't animate the menu items for low end devices. if (!SysUtils.isLowEndDevice() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mPopup .getListView() .addOnLayoutChangeListener( new View.OnLayoutChangeListener() { @Override public void onLayoutChange( View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { mPopup.getListView().removeOnLayoutChangeListener(this); runMenuItemEnterAnimations(); } }); } }
/** * Creates a new tab and posts to UI. * * @param loadUrlParams parameters of the url load. * @param type Information about how the tab was launched. * @param parent the parent tab, if present. * @param position the requested position (index in the tab model) * @param intent the source of the url if it isn't null. * @return The new tab. */ public ChromeTab createNewTab( LoadUrlParams loadUrlParams, TabModel.TabLaunchType type, Tab parent, int position, Intent intent) { try { TraceEvent.begin("ChromeTabCreator.createNewTab"); int parentId = parent != null ? parent.getId() : Tab.INVALID_TAB_ID; WebContents webContents = IntentHandler.getWebContentsFromIntent(intent); boolean isWebContentsPaused = false; if (webContents != null) { // The WebContents comes with additional data, but it shouldn't be used if the // WebContents itself couldn't be parsed out. parentId = IntentUtils.safeGetIntExtra( intent, IntentHandler.EXTRA_PARENT_TAB_ID, Tab.INVALID_TAB_ID); isWebContentsPaused = IntentUtils.safeGetBooleanExtra(intent, IntentHandler.EXTRA_WEB_CONTENTS_PAUSED, false); } // Sanitize the url. loadUrlParams.setUrl(UrlUtilities.fixupUrl(loadUrlParams.getUrl())); loadUrlParams.setTransitionType(getTransitionType(type)); boolean openInForeground = mOrderController.willOpenInForeground(type, mIncognito) || webContents != null; ChromeTab tab; if (webContents != null) { tab = ChromeTab.createLiveTab( Tab.INVALID_TAB_ID, mActivity, mIncognito, mNativeWindow, type, parentId, !openInForeground); tab.initialize(webContents, mTabContentManager, !openInForeground); tab.getTabRedirectHandler().updateIntent(intent); if (isWebContentsPaused) webContents.resumeLoadingCreatedWebContents(); } else if (!openInForeground && SysUtils.isLowEndDevice()) { // On low memory devices the tabs opened in background are not loaded automatically // to preserve resources (cpu, memory, strong renderer binding) for the foreground // tab. tab = ChromeTab.createTabForLazyLoad( mActivity, mIncognito, mNativeWindow, type, parentId, loadUrlParams); tab.initialize(null, mTabContentManager, !openInForeground); mTabSaver.addTabToSaveQueue(tab); tab.getTabRedirectHandler().updateIntent(intent); } else { tab = ChromeTab.createLiveTab( Tab.INVALID_TAB_ID, mActivity, mIncognito, mNativeWindow, type, parentId, !openInForeground); webContents = WarmupManager.getInstance().hasPrerenderedUrl(loadUrlParams.getUrl()) ? WarmupManager.getInstance().takePrerenderedWebContents() : null; tab.initialize(webContents, mTabContentManager, !openInForeground); tab.getTabRedirectHandler().updateIntent(intent); tab.loadUrl(loadUrlParams); } if (intent != null && intent.hasExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA)) { ServiceTabLauncher.onWebContentsForRequestAvailable( intent.getIntExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA, 0), tab.getWebContents()); } mTabModel.addTab(tab, position, type); return tab; } finally { TraceEvent.end("ChromeTabCreator.createNewTab"); } }