Java Examples for android.view.ViewRootImpl
The following java examples will help you to understand the usage of android.view.ViewRootImpl. These source code samples are taken from different open source projects.
Example 1
| Project: robolectric-master File: ShadowActivityTest.java View source code |
@Test
public void decorViewSizeEqualToDisplaySize() {
Activity activity = buildActivity(Activity.class).create().visible().get();
View decorView = activity.getWindow().getDecorView();
assertThat(decorView).isNotEqualTo(null);
ViewRootImpl root = decorView.getViewRootImpl();
assertThat(root).isNotEqualTo(null);
assertThat(decorView.getWidth()).isNotEqualTo(0);
assertThat(decorView.getHeight()).isNotEqualTo(0);
Display display = Shadow.newInstanceOf(Display.class);
ShadowDisplay shadowDisplay = Shadows.shadowOf(display);
assertThat(decorView.getWidth()).isEqualTo(shadowDisplay.getWidth());
assertThat(decorView.getHeight()).isEqualTo(shadowDisplay.getHeight());
}Example 2
| Project: InputMethodHolder-master File: MainActivity.java View source code |
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et = (EditText) findViewById(R.id.et);
btnHook = (Button) findViewById(R.id.btn_init);
btnClose = (Button) findViewById(R.id.btn_close_input);
onInputMethodListener = new OnInputMethodListener() {
@Override
public void onShow(boolean result) {
Toast.makeText(MainActivity.this, "Show input method! " + result, Toast.LENGTH_SHORT).show();
}
@Override
public void onHide(boolean result) {
Toast.makeText(MainActivity.this, "Hide input method! " + result, Toast.LENGTH_SHORT).show();
}
};
InputMethodHolder.registerListener(onInputMethodListener);
//FIXME 在这初始化会失败,目前只能在Application中
// Caused by: java.lang.IllegalArgumentException: unknown client android.os.BinderProxy@2df668f
// at android.os.Parcel.readException(Parcel.java:1624)
// at android.os.Parcel.readException(Parcel.java:1573)
// at com.android.internal.view.IInputMethodManager$Stub$Proxy.windowGainedFocus(IInputMethodManager.java:733)
// at java.lang.reflect.Method.invoke(Native Method)
// at pw.qlm.inputmethodholder.hook.InputMethodManagerHook.invoke(InputMethodManagerHook.java:38)
// at java.lang.reflect.Proxy.invoke(Proxy.java:393)
// at $Proxy1.windowGainedFocus(Unknown Source)
// at android.view.inputmethod.InputMethodManager.startInputInner(InputMethodManager.java:1226)
// at android.view.inputmethod.InputMethodManager.onPostWindowFocus(InputMethodManager.java:1445)
// at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3394)
// at android.os.Handler.dispatchMessage(Handler.java:102)
// at android.os.Looper.loop(Looper.java:148)
// at android.app.ActivityThread.main(ActivityThread.java:5461)
// at java.lang.reflect.Method.invoke(Native Method)
// at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
// at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
btnHook.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
InputMethodHolder.init(getApplication().getBaseContext());
}
});
btnClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(et.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
});
}Example 3
| Project: android-viewer-for-khan-academy-master File: VideoFragment.java View source code |
/*
* Errors: (returnCode, errorCode)
*
* https://github.com/android/platform_external_opencore/blob/master/pvmi/pvmf/include/pvmf_return_codes.h
*
* (1,-12) overflow
* (100, 0)
* (1, -2147483648) // read in a so post this might be invalid stream type
* // or Content-Length header > MAX_INT: http://code.google.com/p/android/issues/detail?id=8624
* (-38, 0) // http://lab-programming.blogspot.com/2012/01/how-to-work-around-android-mediaplayer.html
* (1, -1004) // io error, possibly 500 response, see http://stackoverflow.com/a/8244780/931277
* // Got this one when seeking past the downloaded portion of a partially finished download.
*
* Names of some codes between -1000 and -1014: http://android.joao.jp/2011/07/mediaplayer-errors.html
* Interesting - says to close AssetFileDescriptor; may be similar with ParcelFileDescriptor, eh? http://stackoverflow.com/a/11069306/931277
*
* Out of memory with about 20 video detail views stacked up.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup root, Bundle savedInstanceState) {
ViewGroup container = (ViewGroup) inflater.inflate(R.layout.fragment_video, root, false);
videoView = (VideoView) container.findViewById(R.id.videoView);
controls = (VideoController) container.findViewById(R.id.controller);
controls.setVideoView(videoView);
controls.setCallbacks(this);
controls.setFullscreenRequestHandler(new VideoController.FullscreenRequestHandler() {
@Override
public void onFullscreenToggleRequested() {
for (Callbacks c : callbacks) {
c.onFullscreenToggleRequested();
}
}
});
videoView.setOnCompletionListener(controls);
loadingIndicator = new ProgressBar(getActivity());
RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
p.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
container.addView(loadingIndicator, p);
loadingIndicator.setVisibility(View.GONE);
errorView = inflater.inflate(R.layout.missing_video, container, false);
errorText = (TextView) errorView.findViewById(R.id.text_missing_video);
container.addView(errorView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
errorView.setVisibility(View.GONE);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
int seekTo = getArguments().getInt(Constants.PARAM_VIDEO_POSITION, 0);
boolean playing = getArguments().getBoolean(Constants.PARAM_VIDEO_PLAY_STATE, false);
seekTo(seekTo);
loadingIndicator.setVisibility(View.GONE);
controls.onPrepared(mp);
for (Callbacks c : callbacks) {
c.onVideoPrepared();
}
if (playing) {
controls.play();
}
}
});
positionUpdater.start();
return container;
// Setting the following listener causes a crash on Fire HD. For some reason, orientation changes occasionally (usually within about 20 tries)
// yield the following stack trace, then the device reboots.
/*
* 01-09 17:02:33.537: W/HardwareRenderer(3319): EGL error: EGL_BAD_NATIVE_WINDOW
01-09 17:02:33.576: W/HardwareRenderer(3319): Mountain View, we've had a problem here. Switching back to software rendering.
01-09 17:02:33.584: E/ViewRootImpl(3319): IllegalArgumentException locking surface
01-09 17:02:33.584: E/ViewRootImpl(3319): java.lang.IllegalArgumentException
01-09 17:02:33.584: E/ViewRootImpl(3319): at android.view.Surface.lockCanvasNative(Native Method)
01-09 17:02:33.584: E/ViewRootImpl(3319): at android.view.Surface.lockCanvas(Surface.java:76)
01-09 17:02:33.584: E/ViewRootImpl(3319): at android.view.ViewRootImpl.draw(ViewRootImpl.java:1959)
01-09 17:02:33.584: E/ViewRootImpl(3319): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1647)
01-09 17:02:33.584: E/ViewRootImpl(3319): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2462)
01-09 17:02:33.584: E/ViewRootImpl(3319): at android.os.Handler.dispatchMessage(Handler.java:99)
01-09 17:02:33.584: E/ViewRootImpl(3319): at android.os.Looper.loop(Looper.java:137)
01-09 17:02:33.584: E/ViewRootImpl(3319): at android.app.ActivityThread.main(ActivityThread.java:4486)
01-09 17:02:33.584: E/ViewRootImpl(3319): at java.lang.reflect.Method.invokeNative(Native Method)
01-09 17:02:33.584: E/ViewRootImpl(3319): at java.lang.reflect.Method.invoke(Method.java:511)
01-09 17:02:33.584: E/ViewRootImpl(3319): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-09 17:02:33.584: E/ViewRootImpl(3319): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-09 17:02:33.584: E/ViewRootImpl(3319): at dalvik.system.NativeStart.main(Native Method)
01-09 17:02:34.654: E/InputQueue-JNI(3319): channel '4181fe60 com.concentricsky.android.khanacademy/com.concentricsky.android.khanacademy.app.VideoListActivity (client)' ~ Publisher closed input channel or an error occurred. events=0x8
01-09 17:02:34.662: E/InputQueue-JNI(3319): channel '41841178 com.concentricsky.android.khanacademy/com.concentricsky.android.khanacademy.app.VideoDetailActivity (client)' ~ Publisher closed input channel or an error occurred. events=0x8
01-09 17:02:34.662: E/InputQueue-JNI(3319): channel '417e04b0 com.concentricsky.android.khanacademy/com.concentricsky.android.khanacademy.app.HomeActivity (client)' ~ Publisher closed input channel or an error occurred. events=0x8
*/
// This happens even without the call to `error`, which shows a Toast.
// Looking at the 4.0.3 source on Grepcode, I cannot see how this listener could cause such a problem. I can only guess there is a bug in Amazon's
// VideoView implementation. The one thing that Google's implementation does before calling the provided listener is to set VideoView#mCurrentState
// to STATE_ERROR. It's possible that setting an error listener overwrites the default one in Amazon's implementation, removing some critical piece
// of functionality. Just a guess.
// videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
// @Override
// public boolean onError(MediaPlayer mp, int what, int extra) {
// Log.e(LOG_TAG, String.format("Error: (%d,%d)", what, extra));
// switch (what) {
// case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
// case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
// case MediaPlayer.MEDIA_ERROR_UNKNOWN:
//// error(errorVideoPlayback);
// }
// return false;
// }
// });
}Example 4
| Project: AisenWeiBo-master File: AisenTextView.java View source code |
@Override
public Boolean workInBackground(Void... params) throws TaskException {
TextView textView = textViewRef.get();
if (textView == null)
return false;
if (TextUtils.isEmpty(textView.getText()))
return false;
// android.view.ViewRootImpl$CalledFromWrongThreadException Only the original thread that created a view hierarchy can touch its views.
// 把getText + 一个空字符试试,可能是直接取值会刷UI
String text = textView.getText() + "";
SpannableString spannableString = SpannableString.valueOf(text);
Matcher localMatcher = Pattern.compile("\\[(\\S+?)\\]").matcher(spannableString);
while (localMatcher.find()) {
if (isCancelled())
break;
String key = localMatcher.group(0);
int k = localMatcher.start();
int m = localMatcher.end();
byte[] data = EmotionsDB.getEmotion(key);
if (data == null)
continue;
MyBitmap mb = BitmapLoader.getInstance().getImageCache().getBitmapFromMemCache(key, null);
Bitmap b = null;
if (mb != null) {
b = mb.getBitmap();
} else {
b = BitmapFactory.decodeByteArray(data, 0, data.length);
int size = BaseActivity.getRunningActivity().getResources().getDimensionPixelSize(R.dimen.emotion_size);
b = BitmapUtil.zoomBitmap(b, size);
// 添加到内存中
BitmapLoader.getInstance().getImageCache().addBitmapToMemCache(key, null, new MyBitmap(b, key));
}
ImageSpan l = new ImageSpan(GlobalContext.getInstance(), b, ImageSpan.ALIGN_BASELINE);
spannableString.setSpan(l, k, m, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
// 用户名称
// Pattern pattern = Pattern.compile("@([a-zA-Z0-9_\\-\\u4e00-\\u9fa5]+)");
Pattern pattern = Pattern.compile("@[\\w\\p{InCJKUnifiedIdeographs}-]{1,26}");
String scheme = "org.aisen.weibo.sina.userinfo://";
Linkify.addLinks(spannableString, pattern, scheme);
// 网页链接
scheme = "http://";
// 启用内置浏览器
if (AppSettings.isInnerBrower())
scheme = "aisen://";
Linkify.addLinks(spannableString, Pattern.compile("http://[a-zA-Z0-9+&@#/%?=~_\\-|!:,\\.;]*[a-zA-Z0-9+&@#/%=~_|]"), scheme);
// 话题
Pattern dd = Pattern.compile("#[\\p{Print}\\p{InCJKUnifiedIdeographs}&&[^#]]+#");
//Pattern dd = Pattern.compile("#([a-zA-Z0-9_\\-\\u4e00-\\u9fa5]+)#");
scheme = "org.aisen.weibo.sina.topics://";
Linkify.addLinks(spannableString, dd, scheme);
URLSpan[] urlSpans = spannableString.getSpans(0, spannableString.length(), URLSpan.class);
MyURLSpan weiboSpan = null;
for (URLSpan urlSpan : urlSpans) {
weiboSpan = new MyURLSpan(urlSpan.getURL());
// if (AppSettings.isHightlight())
// weiboSpan.setColor(Color.parseColor(color));
// else
// weiboSpan.setColor(0);
int start = spannableString.getSpanStart(urlSpan);
int end = spannableString.getSpanEnd(urlSpan);
try {
spannableString.removeSpan(urlSpan);
} catch (Exception e) {
}
spannableString.setSpan(weiboSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
publishProgress(spannableString);
String key = KeyGenerator.generateMD5(spannableString.toString());
stringMemoryCache.put(key, spannableString);
Logger.v(TAG, String.format("添加spannable到内存中,现在共有%d个spannable", stringMemoryCache.size()));
return null;
}Example 5
| Project: Hews-master File: PopupFloatingWindow.java View source code |
public void show() {
preShow();
//Error
// android.view.WindowManager$BadTokenException:
// Unable to add window -- token android.view.ViewRootImpl$W@2274902e is not valid;
// is your activity running?
// Added android:spinnerMode="dialog" in xml
// mWindow.showAtLocation(((Activity) mContext).getWindow().
//getDecorView().findViewById(android.R.id.content), Gravity.NO_GRAVITY, 20, 200);
mWindow.showAsDropDown(mAttachView, 0, 0);
isShowing = true;
}Example 6
| Project: XieDaDeng-master File: StatusBarWindowView.java View source code |
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mStackScrollLayout = (NotificationStackScrollLayout) findViewById(R.id.notification_stack_scroller);
mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
mBrightnessMirror = findViewById(R.id.brightness_mirror);
// We really need to be able to animate while window animations are going on
// so that activities may be started asynchronously from panel animations
final ViewRootImpl root = getViewRootImpl();
if (root != null) {
root.setDrawDuringWindowsAnimating(true);
}
// the scrim, we don't need the window to be cleared in the beginning.
if (mService.isScrimSrcModeEnabled()) {
IBinder windowToken = getWindowToken();
WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
lp.token = windowToken;
setLayoutParams(lp);
WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
setWillNotDraw(false);
} else {
setWillNotDraw(!DEBUG);
}
}Example 7
| Project: screenshot-tests-for-android-master File: WindowAttachment.java View source code |
/**
* Simulates the view as being attached.
*/
public static void setAttachInfo(View view) {
try {
Class cAttachInfo = Class.forName("android.view.View$AttachInfo");
Class cViewRootImpl = null;
if (Build.VERSION.SDK_INT >= 11) {
cViewRootImpl = Class.forName("android.view.ViewRootImpl");
}
Class cIWindowSession = Class.forName("android.view.IWindowSession");
Class cIWindow = Class.forName("android.view.IWindow");
Class cCallbacks = Class.forName("android.view.View$AttachInfo$Callbacks");
Context context = view.getContext();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Object viewRootImpl = null;
Object window = createIWindow();
Class[] params = null;
Object[] values = null;
if (Build.VERSION.SDK_INT >= 17) {
viewRootImpl = cViewRootImpl.getConstructor(Context.class, Display.class).newInstance(context, display);
params = new Class[] { cIWindowSession, cIWindow, Display.class, cViewRootImpl, Handler.class, cCallbacks };
values = new Object[] { stub(cIWindowSession), window, display, viewRootImpl, new Handler(), stub(cCallbacks) };
} else if (Build.VERSION.SDK_INT >= 16) {
viewRootImpl = cViewRootImpl.getConstructor(Context.class).newInstance(context);
params = new Class[] { cIWindowSession, cIWindow, cViewRootImpl, Handler.class, cCallbacks };
values = new Object[] { stub(cIWindowSession), window, viewRootImpl, new Handler(), stub(cCallbacks) };
} else if (Build.VERSION.SDK_INT <= 15) {
params = new Class[] { cIWindowSession, cIWindow, Handler.class, cCallbacks };
values = new Object[] { stub(cIWindowSession), window, new Handler(), stub(cCallbacks) };
}
Object attachInfo = invokeConstructor(cAttachInfo, params, values);
setField(attachInfo, "mHasWindowFocus", true);
setField(attachInfo, "mWindowVisibility", View.VISIBLE);
setField(attachInfo, "mInTouchMode", false);
if (Build.VERSION.SDK_INT >= 11) {
setField(attachInfo, "mHardwareAccelerated", false);
}
Method dispatch = View.class.getDeclaredMethod("dispatchAttachedToWindow", cAttachInfo, int.class);
dispatch.setAccessible(true);
dispatch.invoke(view, attachInfo, 0);
} catch (Exception e) {
throw new RuntimeException(e);
}
}Example 8
| Project: frameworks_base_disabled-master File: PasswordEntryKeyboardHelper.java View source code |
private void sendKeyEventsToTarget(int character) {
ViewRootImpl viewRootImpl = mTargetView.getViewRootImpl();
KeyEvent[] events = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD).getEvents(new char[] { (char) character });
if (events != null) {
final int N = events.length;
for (int i = 0; i < N; i++) {
KeyEvent event = events[i];
event = KeyEvent.changeFlags(event, event.getFlags() | KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
viewRootImpl.dispatchKey(event);
}
}
}Example 9
| Project: AndroidN-ify-master File: QSAnimator.java View source code |
private void getRelativePositionInt(int[] loc1, View view, View parent) {
if (view == parent || view == null)
return;
// RTL.
if (!(view instanceof PagedTileLayout.TilePage)) {
loc1[0] += view.getLeft();
loc1[1] += view.getTop();
}
if (!(view.getParent() instanceof ViewRootImpl))
getRelativePositionInt(loc1, (View) view.getParent(), parent);
}Example 10
| Project: XposedAppSettings-master File: Activities.java View source code |
public static void hookActivitySettings() {
try {
findAndHookMethod("com.android.internal.policy.impl.PhoneWindow", null, "generateLayout", "com.android.internal.policy.impl.PhoneWindow.DecorView", new XC_MethodHook() {
@SuppressLint("InlinedApi")
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Window window = (Window) param.thisObject;
View decorView = (View) param.args[0];
Context context = window.getContext();
String packageName = context.getPackageName();
if (!XposedMod.isActive(packageName))
return;
int fullscreen;
try {
fullscreen = XposedMod.prefs.getInt(packageName + Common.PREF_FULLSCREEN, Common.FULLSCREEN_DEFAULT);
} catch (ClassCastException ex) {
fullscreen = XposedMod.prefs.getBoolean(packageName + Common.PREF_FULLSCREEN, false) ? Common.FULLSCREEN_FORCE : Common.FULLSCREEN_DEFAULT;
}
if (fullscreen == Common.FULLSCREEN_FORCE) {
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setAdditionalInstanceField(window, PROP_FULLSCREEN, Boolean.TRUE);
} else if (fullscreen == Common.FULLSCREEN_PREVENT) {
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setAdditionalInstanceField(window, PROP_FULLSCREEN, Boolean.FALSE);
} else if (fullscreen == Common.FULLSCREEN_IMMERSIVE && Build.VERSION.SDK_INT >= 19) {
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setAdditionalInstanceField(window, PROP_FULLSCREEN, Boolean.TRUE);
setAdditionalInstanceField(decorView, PROP_IMMERSIVE, Boolean.TRUE);
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
if (XposedMod.prefs.getBoolean(packageName + Common.PREF_NO_TITLE, false))
window.requestFeature(Window.FEATURE_NO_TITLE);
if (XposedMod.prefs.getBoolean(packageName + Common.PREF_ALLOW_ON_LOCKSCREEN, false))
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
if (XposedMod.prefs.getBoolean(packageName + Common.PREF_SCREEN_ON, false)) {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setAdditionalInstanceField(window, PROP_KEEP_SCREEN_ON, Boolean.TRUE);
}
if (XposedMod.prefs.getBoolean(packageName + Common.PREF_LEGACY_MENU, false)) {
window.setFlags(FLAG_NEEDS_MENU_KEY, FLAG_NEEDS_MENU_KEY);
setAdditionalInstanceField(window, PROP_LEGACY_MENU, Boolean.TRUE);
}
int orientation = XposedMod.prefs.getInt(packageName + Common.PREF_ORIENTATION, XposedMod.prefs.getInt(Common.PREF_DEFAULT + Common.PREF_ORIENTATION, 0));
if (orientation > 0 && orientation < Common.orientationCodes.length && context instanceof Activity) {
((Activity) context).setRequestedOrientation(Common.orientationCodes[orientation]);
setAdditionalInstanceField(context, PROP_ORIENTATION, orientation);
}
}
});
} catch (Throwable e) {
XposedBridge.log(e);
}
try {
findAndHookMethod(Window.class, "setFlags", int.class, int.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
int flags = (Integer) param.args[0];
int mask = (Integer) param.args[1];
if ((mask & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
Boolean fullscreen = (Boolean) getAdditionalInstanceField(param.thisObject, PROP_FULLSCREEN);
if (fullscreen != null) {
if (fullscreen.booleanValue()) {
flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
} else {
flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
}
param.args[0] = flags;
}
}
if ((mask & WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0) {
Boolean keepScreenOn = (Boolean) getAdditionalInstanceField(param.thisObject, PROP_KEEP_SCREEN_ON);
if (keepScreenOn != null) {
if (keepScreenOn.booleanValue()) {
flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
}
param.args[0] = flags;
}
}
if ((mask & FLAG_NEEDS_MENU_KEY) != 0) {
Boolean menu = (Boolean) getAdditionalInstanceField(param.thisObject, PROP_LEGACY_MENU);
if (menu != null) {
if (menu.booleanValue()) {
flags |= FLAG_NEEDS_MENU_KEY;
}
param.args[0] = flags;
}
}
}
});
} catch (Throwable e) {
XposedBridge.log(e);
}
if (Build.VERSION.SDK_INT >= 19) {
try {
findAndHookMethod("android.view.ViewRootImpl", null, "dispatchSystemUiVisibilityChanged", int.class, int.class, int.class, int.class, new XC_MethodHook() {
@TargetApi(19)
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// Has the navigation bar been shown?
int localChanges = (Integer) param.args[3];
if ((localChanges & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0)
return;
// Should it be hidden?
View decorView = (View) getObjectField(param.thisObject, "mView");
Boolean immersive = (decorView == null) ? null : (Boolean) getAdditionalInstanceField(decorView, PROP_IMMERSIVE);
if (immersive == null || !immersive.booleanValue())
return;
// Enforce SYSTEM_UI_FLAG_HIDE_NAVIGATION and hide changes to this flag
int globalVisibility = (Integer) param.args[1];
int localValue = (Integer) param.args[2];
param.args[1] = globalVisibility | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
param.args[2] = localValue | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
param.args[3] = localChanges & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
});
} catch (Throwable e) {
XposedBridge.log(e);
}
}
try {
findAndHookMethod(Activity.class, "setRequestedOrientation", int.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Integer orientation = (Integer) getAdditionalInstanceField(param.thisObject, PROP_ORIENTATION);
if (orientation != null)
param.args[0] = Common.orientationCodes[orientation];
}
});
} catch (Throwable e) {
XposedBridge.log(e);
}
try {
// Hook one of the several variations of ActivityStack.realStartActivityLocked from different ROMs
Method mthRealStartActivityLocked;
if (Build.VERSION.SDK_INT <= 18) {
try {
mthRealStartActivityLocked = findMethodExact("com.android.server.am.ActivityStack", null, "realStartActivityLocked", "com.android.server.am.ActivityRecord", "com.android.server.am.ProcessRecord", boolean.class, boolean.class, boolean.class);
} catch (NoSuchMethodError t) {
mthRealStartActivityLocked = findMethodExact("com.android.server.am.ActivityStack", null, "realStartActivityLocked", "com.android.server.am.ActivityRecord", "com.android.server.am.ProcessRecord", boolean.class, boolean.class);
}
} else {
mthRealStartActivityLocked = findMethodExact("com.android.server.am.ActivityStackSupervisor", null, "realStartActivityLocked", "com.android.server.am.ActivityRecord", "com.android.server.am.ProcessRecord", boolean.class, boolean.class);
}
hookMethod(mthRealStartActivityLocked, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String pkgName = (String) getObjectField(param.args[0], "packageName");
if (XposedMod.isActive(pkgName, Common.PREF_RESIDENT)) {
int adj = -12;
Object proc = getObjectField(param.args[0], "app");
// Override the *Adj values if meant to be resident in memory
if (proc != null) {
setIntField(proc, "maxAdj", adj);
if (Build.VERSION.SDK_INT <= 18)
setIntField(proc, "hiddenAdj", adj);
setIntField(proc, "curRawAdj", adj);
setIntField(proc, "setRawAdj", adj);
setIntField(proc, "curAdj", adj);
setIntField(proc, "setAdj", adj);
}
}
}
});
} catch (Throwable e) {
XposedBridge.log(e);
}
try {
hookAllConstructors(findClass("com.android.server.am.ActivityRecord", null), new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
ActivityInfo aInfo = (ActivityInfo) getObjectField(param.thisObject, "info");
if (aInfo == null)
return;
String pkgName = aInfo.packageName;
if (XposedMod.prefs.getInt(pkgName + Common.PREF_RECENTS_MODE, Common.PREF_RECENTS_DEFAULT) > 0) {
int recentsMode = XposedMod.prefs.getInt(pkgName + Common.PREF_RECENTS_MODE, Common.PREF_RECENTS_DEFAULT);
if (recentsMode == Common.PREF_RECENTS_DEFAULT)
return;
Intent intent = (Intent) getObjectField(param.thisObject, "intent");
if (recentsMode == Common.PREF_RECENTS_FORCE) {
int flags = (intent.getFlags() & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.setFlags(flags);
} else if (recentsMode == Common.PREF_RECENTS_PREVENT)
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
}
}
});
} catch (Throwable e) {
XposedBridge.log(e);
}
try {
findAndHookMethod(InputMethodService.class, "doStartInput", InputConnection.class, EditorInfo.class, boolean.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
EditorInfo info = (EditorInfo) param.args[1];
if (info != null && info.packageName != null) {
XposedMod.prefs.reload();
if (XposedMod.isActive(info.packageName, Common.PREF_NO_FULLSCREEN_IME))
info.imeOptions |= EditorInfo.IME_FLAG_NO_FULLSCREEN;
}
}
});
} catch (Throwable e) {
XposedBridge.log(e);
}
}Example 11
| Project: cnAndroidDocs-master File: ListView.java View source code |
@Override
protected void layoutChildren() {
final boolean blockLayoutRequests = mBlockLayoutRequests;
if (!blockLayoutRequests) {
mBlockLayoutRequests = true;
} else {
return;
}
try {
super.layoutChildren();
invalidate();
if (mAdapter == null) {
resetList();
invokeOnItemScrollListener();
return;
}
int childrenTop = mListPadding.top;
int childrenBottom = mBottom - mTop - mListPadding.bottom;
int childCount = getChildCount();
int index = 0;
int delta = 0;
View sel;
View oldSel = null;
View oldFirst = null;
View newSel = null;
View focusLayoutRestoreView = null;
AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null;
View accessibilityFocusLayoutRestoreView = null;
int accessibilityFocusPosition = INVALID_POSITION;
// Remember stuff we will need down below
switch(mLayoutMode) {
case LAYOUT_SET_SELECTION:
index = mNextSelectedPosition - mFirstPosition;
if (index >= 0 && index < childCount) {
newSel = getChildAt(index);
}
break;
case LAYOUT_FORCE_TOP:
case LAYOUT_FORCE_BOTTOM:
case LAYOUT_SPECIFIC:
case LAYOUT_SYNC:
break;
case LAYOUT_MOVE_SELECTION:
default:
// Remember the previously selected view
index = mSelectedPosition - mFirstPosition;
if (index >= 0 && index < childCount) {
oldSel = getChildAt(index);
}
// Remember the previous first child
oldFirst = getChildAt(0);
if (mNextSelectedPosition >= 0) {
delta = mNextSelectedPosition - mSelectedPosition;
}
// Caution: newSel might be null
newSel = getChildAt(index + delta);
}
boolean dataChanged = mDataChanged;
if (dataChanged) {
handleDataChanged();
}
// and calling it a day
if (mItemCount == 0) {
resetList();
invokeOnItemScrollListener();
return;
} else if (mItemCount != mAdapter.getCount()) {
throw new IllegalStateException("The content of the adapter has changed but " + "ListView did not receive a notification. Make sure the content of " + "your adapter is not modified from a background thread, but only " + "from the UI thread. [in ListView(" + getId() + ", " + getClass() + ") with Adapter(" + mAdapter.getClass() + ")]");
}
setSelectedPositionInt(mNextSelectedPosition);
// Pull all children into the RecycleBin.
// These views will be reused if possible
final int firstPosition = mFirstPosition;
final RecycleBin recycleBin = mRecycler;
// reset the focus restoration
View focusLayoutRestoreDirectChild = null;
// already cached in mHeaderViews;
if (dataChanged) {
for (int i = 0; i < childCount; i++) {
recycleBin.addScrapView(getChildAt(i), firstPosition + i);
}
} else {
recycleBin.fillActiveViews(childCount, firstPosition);
}
// take focus back to us temporarily to avoid the eventual
// call to clear focus when removing the focused child below
// from messing things up when ViewAncestor assigns focus back
// to someone else
final View focusedChild = getFocusedChild();
if (focusedChild != null) {
// data hasn't changed, or if the focused position is a header or footer
if (!dataChanged || isDirectChildHeaderOrFooter(focusedChild)) {
focusLayoutRestoreDirectChild = focusedChild;
// remember the specific view that had focus
focusLayoutRestoreView = findFocus();
if (focusLayoutRestoreView != null) {
// tell it we are going to mess with it
focusLayoutRestoreView.onStartTemporaryDetach();
}
}
requestFocus();
}
// Remember which child, if any, had accessibility focus.
final ViewRootImpl viewRootImpl = getViewRootImpl();
if (viewRootImpl != null) {
final View accessFocusedView = viewRootImpl.getAccessibilityFocusedHost();
if (accessFocusedView != null) {
final View accessFocusedChild = findAccessibilityFocusedChild(accessFocusedView);
if (accessFocusedChild != null) {
if (!dataChanged || isDirectChildHeaderOrFooter(accessFocusedChild)) {
// If the views won't be changing, try to maintain
// focus on the current view host and (if
// applicable) its virtual view.
accessibilityFocusLayoutRestoreView = accessFocusedView;
accessibilityFocusLayoutRestoreNode = viewRootImpl.getAccessibilityFocusedVirtualView();
} else {
// Otherwise, try to maintain focus at the same
// position.
accessibilityFocusPosition = getPositionForView(accessFocusedChild);
}
}
}
}
// Clear out old views
detachAllViewsFromParent();
recycleBin.removeSkippedScrap();
switch(mLayoutMode) {
case LAYOUT_SET_SELECTION:
if (newSel != null) {
sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom);
} else {
sel = fillFromMiddle(childrenTop, childrenBottom);
}
break;
case LAYOUT_SYNC:
sel = fillSpecific(mSyncPosition, mSpecificTop);
break;
case LAYOUT_FORCE_BOTTOM:
sel = fillUp(mItemCount - 1, childrenBottom);
adjustViewsUpOrDown();
break;
case LAYOUT_FORCE_TOP:
mFirstPosition = 0;
sel = fillFromTop(childrenTop);
adjustViewsUpOrDown();
break;
case LAYOUT_SPECIFIC:
sel = fillSpecific(reconcileSelectedPosition(), mSpecificTop);
break;
case LAYOUT_MOVE_SELECTION:
sel = moveSelection(oldSel, newSel, delta, childrenTop, childrenBottom);
break;
default:
if (childCount == 0) {
if (!mStackFromBottom) {
final int position = lookForSelectablePosition(0, true);
setSelectedPositionInt(position);
sel = fillFromTop(childrenTop);
} else {
final int position = lookForSelectablePosition(mItemCount - 1, false);
setSelectedPositionInt(position);
sel = fillUp(mItemCount - 1, childrenBottom);
}
} else {
if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) {
sel = fillSpecific(mSelectedPosition, oldSel == null ? childrenTop : oldSel.getTop());
} else if (mFirstPosition < mItemCount) {
sel = fillSpecific(mFirstPosition, oldFirst == null ? childrenTop : oldFirst.getTop());
} else {
sel = fillSpecific(0, childrenTop);
}
}
break;
}
// Flush any cached views that did not get reused above
recycleBin.scrapActiveViews();
if (sel != null) {
// are focusable
if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) {
final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild && focusLayoutRestoreView != null && focusLayoutRestoreView.requestFocus()) || sel.requestFocus();
if (!focusWasTaken) {
// selected item didn't take focus, fine, but still want
// to make sure something else outside of the selected view
// has focus
final View focused = getFocusedChild();
if (focused != null) {
focused.clearFocus();
}
positionSelector(INVALID_POSITION, sel);
} else {
sel.setSelected(false);
mSelectorRect.setEmpty();
}
} else {
positionSelector(INVALID_POSITION, sel);
}
mSelectedTop = sel.getTop();
} else {
if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) {
View child = getChildAt(mMotionPosition - mFirstPosition);
if (child != null)
positionSelector(mMotionPosition, child);
} else {
mSelectedTop = 0;
mSelectorRect.setEmpty();
}
// focus (i.e. something focusable in touch mode)
if (hasFocus() && focusLayoutRestoreView != null) {
focusLayoutRestoreView.requestFocus();
}
}
// Attempt to restore accessibility focus.
if (accessibilityFocusLayoutRestoreNode != null) {
accessibilityFocusLayoutRestoreNode.performAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
} else if (accessibilityFocusLayoutRestoreView != null) {
accessibilityFocusLayoutRestoreView.requestAccessibilityFocus();
} else if (accessibilityFocusPosition != INVALID_POSITION) {
// Bound the position within the visible children.
final int position = MathUtils.constrain((accessibilityFocusPosition - mFirstPosition), 0, (getChildCount() - 1));
final View restoreView = getChildAt(position);
if (restoreView != null) {
restoreView.requestAccessibilityFocus();
}
}
// our view hierarchy.
if (focusLayoutRestoreView != null && focusLayoutRestoreView.getWindowToken() != null) {
focusLayoutRestoreView.onFinishTemporaryDetach();
}
mLayoutMode = LAYOUT_NORMAL;
mDataChanged = false;
if (mPositionScrollAfterLayout != null) {
post(mPositionScrollAfterLayout);
mPositionScrollAfterLayout = null;
}
mNeedSync = false;
setNextSelectedPositionInt(mSelectedPosition);
updateScrollIndicators();
if (mItemCount > 0) {
checkSelectionChanged();
}
invokeOnItemScrollListener();
} finally {
if (!blockLayoutRequests) {
mBlockLayoutRequests = false;
}
}
}Example 12
| Project: platform_frameworks_base-master File: GridView.java View source code |
@Override
protected void layoutChildren() {
final boolean blockLayoutRequests = mBlockLayoutRequests;
if (!blockLayoutRequests) {
mBlockLayoutRequests = true;
}
try {
super.layoutChildren();
invalidate();
if (mAdapter == null) {
resetList();
invokeOnItemScrollListener();
return;
}
final int childrenTop = mListPadding.top;
final int childrenBottom = mBottom - mTop - mListPadding.bottom;
int childCount = getChildCount();
int index;
int delta = 0;
View sel;
View oldSel = null;
View oldFirst = null;
View newSel = null;
// Remember stuff we will need down below
switch(mLayoutMode) {
case LAYOUT_SET_SELECTION:
index = mNextSelectedPosition - mFirstPosition;
if (index >= 0 && index < childCount) {
newSel = getChildAt(index);
}
break;
case LAYOUT_FORCE_TOP:
case LAYOUT_FORCE_BOTTOM:
case LAYOUT_SPECIFIC:
case LAYOUT_SYNC:
break;
case LAYOUT_MOVE_SELECTION:
if (mNextSelectedPosition >= 0) {
delta = mNextSelectedPosition - mSelectedPosition;
}
break;
default:
// Remember the previously selected view
index = mSelectedPosition - mFirstPosition;
if (index >= 0 && index < childCount) {
oldSel = getChildAt(index);
}
// Remember the previous first child
oldFirst = getChildAt(0);
}
boolean dataChanged = mDataChanged;
if (dataChanged) {
handleDataChanged();
}
// and calling it a day
if (mItemCount == 0) {
resetList();
invokeOnItemScrollListener();
return;
}
setSelectedPositionInt(mNextSelectedPosition);
AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null;
View accessibilityFocusLayoutRestoreView = null;
int accessibilityFocusPosition = INVALID_POSITION;
// Remember which child, if any, had accessibility focus. This must
// occur before recycling any views, since that will clear
// accessibility focus.
final ViewRootImpl viewRootImpl = getViewRootImpl();
if (viewRootImpl != null) {
final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
if (focusHost != null) {
final View focusChild = getAccessibilityFocusedChild(focusHost);
if (focusChild != null) {
if (!dataChanged || focusChild.hasTransientState() || mAdapterHasStableIds) {
// The views won't be changing, so try to maintain
// focus on the current host and virtual view.
accessibilityFocusLayoutRestoreView = focusHost;
accessibilityFocusLayoutRestoreNode = viewRootImpl.getAccessibilityFocusedVirtualView();
}
// Try to maintain focus at the same position.
accessibilityFocusPosition = getPositionForView(focusChild);
}
}
}
// Pull all children into the RecycleBin.
// These views will be reused if possible
final int firstPosition = mFirstPosition;
final RecycleBin recycleBin = mRecycler;
if (dataChanged) {
for (int i = 0; i < childCount; i++) {
recycleBin.addScrapView(getChildAt(i), firstPosition + i);
}
} else {
recycleBin.fillActiveViews(childCount, firstPosition);
}
// Clear out old views
detachAllViewsFromParent();
recycleBin.removeSkippedScrap();
switch(mLayoutMode) {
case LAYOUT_SET_SELECTION:
if (newSel != null) {
sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom);
} else {
sel = fillSelection(childrenTop, childrenBottom);
}
break;
case LAYOUT_FORCE_TOP:
mFirstPosition = 0;
sel = fillFromTop(childrenTop);
adjustViewsUpOrDown();
break;
case LAYOUT_FORCE_BOTTOM:
sel = fillUp(mItemCount - 1, childrenBottom);
adjustViewsUpOrDown();
break;
case LAYOUT_SPECIFIC:
sel = fillSpecific(mSelectedPosition, mSpecificTop);
break;
case LAYOUT_SYNC:
sel = fillSpecific(mSyncPosition, mSpecificTop);
break;
case LAYOUT_MOVE_SELECTION:
// Move the selection relative to its old position
sel = moveSelection(delta, childrenTop, childrenBottom);
break;
default:
if (childCount == 0) {
if (!mStackFromBottom) {
setSelectedPositionInt(mAdapter == null || isInTouchMode() ? INVALID_POSITION : 0);
sel = fillFromTop(childrenTop);
} else {
final int last = mItemCount - 1;
setSelectedPositionInt(mAdapter == null || isInTouchMode() ? INVALID_POSITION : last);
sel = fillFromBottom(last, childrenBottom);
}
} else {
if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) {
sel = fillSpecific(mSelectedPosition, oldSel == null ? childrenTop : oldSel.getTop());
} else if (mFirstPosition < mItemCount) {
sel = fillSpecific(mFirstPosition, oldFirst == null ? childrenTop : oldFirst.getTop());
} else {
sel = fillSpecific(0, childrenTop);
}
}
break;
}
// Flush any cached views that did not get reused above
recycleBin.scrapActiveViews();
if (sel != null) {
positionSelector(INVALID_POSITION, sel);
mSelectedTop = sel.getTop();
} else {
final boolean inTouchMode = mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL;
if (inTouchMode) {
// If the user's finger is down, select the motion position.
final View child = getChildAt(mMotionPosition - mFirstPosition);
if (child != null) {
positionSelector(mMotionPosition, child);
}
} else if (mSelectedPosition != INVALID_POSITION) {
// If we had previously positioned the selector somewhere,
// put it back there. It might not match up with the data,
// but it's transitioning out so it's not a big deal.
final View child = getChildAt(mSelectorPosition - mFirstPosition);
if (child != null) {
positionSelector(mSelectorPosition, child);
}
} else {
// Otherwise, clear selection.
mSelectedTop = 0;
mSelectorRect.setEmpty();
}
}
// Attempt to restore accessibility focus, if necessary.
if (viewRootImpl != null) {
final View newAccessibilityFocusedView = viewRootImpl.getAccessibilityFocusedHost();
if (newAccessibilityFocusedView == null) {
if (accessibilityFocusLayoutRestoreView != null && accessibilityFocusLayoutRestoreView.isAttachedToWindow()) {
final AccessibilityNodeProvider provider = accessibilityFocusLayoutRestoreView.getAccessibilityNodeProvider();
if (accessibilityFocusLayoutRestoreNode != null && provider != null) {
final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityFocusLayoutRestoreNode.getSourceNodeId());
provider.performAction(virtualViewId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
} else {
accessibilityFocusLayoutRestoreView.requestAccessibilityFocus();
}
} else if (accessibilityFocusPosition != INVALID_POSITION) {
// Bound the position within the visible children.
final int position = MathUtils.constrain(accessibilityFocusPosition - mFirstPosition, 0, getChildCount() - 1);
final View restoreView = getChildAt(position);
if (restoreView != null) {
restoreView.requestAccessibilityFocus();
}
}
}
}
mLayoutMode = LAYOUT_NORMAL;
mDataChanged = false;
if (mPositionScrollAfterLayout != null) {
post(mPositionScrollAfterLayout);
mPositionScrollAfterLayout = null;
}
mNeedSync = false;
setNextSelectedPositionInt(mSelectedPosition);
updateScrollIndicators();
if (mItemCount > 0) {
checkSelectionChanged();
}
invokeOnItemScrollListener();
} finally {
if (!blockLayoutRequests) {
mBlockLayoutRequests = false;
}
}
}Example 13
| Project: XobotOS-master File: InputMethodManager.java View source code |
/**
* Disconnect any existing input connection, clearing the served view.
*/
void finishInputLocked() {
mNextServedView = null;
if (mServedView != null) {
if (DEBUG)
Log.v(TAG, "FINISH INPUT: " + mServedView);
if (mCurrentTextBoxAttribute != null) {
try {
mService.finishInput(mClient);
} catch (RemoteException e) {
}
}
if (mServedInputConnection != null) {
// We need to tell the previously served view that it is no
// longer the input target, so it can reset its state. Schedule
// this call on its window's Handler so it will be on the correct
// thread and outside of our lock.
Handler vh = mServedView.getHandler();
if (vh != null) {
// This will result in a call to reportFinishInputConnection()
// below.
vh.sendMessage(vh.obtainMessage(ViewRootImpl.FINISH_INPUT_CONNECTION, mServedInputConnection));
}
}
mServedView = null;
mCompletions = null;
mServedConnecting = false;
clearConnectionLocked();
}
}Example 14
| Project: ViewInspector-master File: ViewUtil.java View source code |
public static int getViewLevel(View view) {
int level = 0;
ViewParent parent = view.getParent();
while (parent != null && !parent.toString().contains("android.view.ViewRootImpl")) {
parent = parent.getParent();
level++;
}
return level;
}Example 15
| Project: android-sdk-sources-for-api-level-23-master File: WebViewDelegate.java View source code |
/**
* Returns true if the draw GL functor can be invoked (see {@link #invokeDrawGlFunctor})
* and false otherwise.
*/
public boolean canInvokeDrawGlFunctor(View containerView) {
ViewRootImpl viewRootImpl = containerView.getViewRootImpl();
// viewRootImpl can be null during teardown when window is leaked.
return viewRootImpl != null;
}