package com.sensorsdata.analytics.android.sdk.visual; import a.f; import android.annotation.SuppressLint; import android.app.Activity; import android.content.res.ColorStateList; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; import android.util.Base64OutputStream; import android.util.DisplayMetrics; import android.util.JsonWriter; import android.util.LruCache; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.Window; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.core.view.MotionEventCompat; import com.meizu.cloud.pushsdk.constants.PushConstants; import com.sensorsdata.analytics.android.sdk.AppStateManager; import com.sensorsdata.analytics.android.sdk.SALog; import com.sensorsdata.analytics.android.sdk.SensorsDataAPI; import com.sensorsdata.analytics.android.sdk.SensorsDataAutoTrackHelper; import com.sensorsdata.analytics.android.sdk.util.AopUtil; import com.sensorsdata.analytics.android.sdk.util.DeviceUtils; import com.sensorsdata.analytics.android.sdk.util.ReflectUtil; import com.sensorsdata.analytics.android.sdk.util.ViewUtil; import com.sensorsdata.analytics.android.sdk.util.WindowHelper; import com.sensorsdata.analytics.android.sdk.visual.model.SnapInfo; import com.sensorsdata.analytics.android.sdk.visual.model.ViewNode; import com.sensorsdata.analytics.android.sdk.visual.model.WebNode; import com.sensorsdata.analytics.android.sdk.visual.model.WebNodeInfo; import com.sensorsdata.analytics.android.sdk.visual.snap.Caller; import com.sensorsdata.analytics.android.sdk.visual.snap.PropertyDescription; import com.sensorsdata.analytics.android.sdk.visual.snap.ResourceIds; import com.sensorsdata.analytics.android.sdk.visual.snap.SoftWareCanvas; import com.sensorsdata.analytics.android.sdk.visual.snap.UIThreadSet; import com.sensorsdata.analytics.android.sdk.visual.util.Dispatcher; import com.sensorsdata.analytics.android.sdk.visual.util.VisualUtil; import com.shizhuang.duapp.R; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.security.MessageDigest; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import o5.i; import org.json.JSONObject; public class ViewSnapshot { private AlertRunnable mAlertRunnable; private final ClassNameCache mClassnameCache; private final Handler mMainThreadHandler; private final List<PropertyDescription> mProperties; private final ResourceIds mResourceIds; private final RootViewFinder mRootViewFinder; public SnapInfo mSnapInfo = new SnapInfo(); public static class AlertRunnable implements Runnable { private String url; public AlertRunnable(String str) { this.url = str; } public void run() { if (WebNodesManager.getInstance().getWebNodes(this.url) == null) { SALog.i("SA.Snapshot", "H5 页面未集成 Web JS SDK"); WebNodesManager.getInstance().handlerFailure(this.url, "{\"callType\":\"app_alert\",\"data\":[{\"title\":\"当前页面无法进行可视化全埋点\",\"message\":\"此页面未集成 Web JS SDK 或者 Web JS SDK 版本过低,请集成最新版 Web JS SDK\",\"link_text\":\"配置文档\",\"link_url\":\"https://manual.sensorsdata.cn/sa/latest/tech_sdk_client_web_use-7545346.html\"}]}"); } } } public static class CachedBitmap { private Bitmap mCached = null; private String mImageHash = ""; private final Paint mPaint = new Paint(2); private static byte[] concat(byte[] bArr, byte[] bArr2) { byte[] bArr3 = new byte[(bArr.length + bArr2.length)]; System.arraycopy(bArr, 0, bArr3, 0, bArr.length); System.arraycopy(bArr2, 0, bArr3, bArr.length, bArr2.length); return bArr3; } private String toHex(byte[] bArr) { String str = ""; for (int i = 0; i < bArr.length; i++) { StringBuilder h12 = f.h(str); h12.append("0123456789ABCDEF".charAt((bArr[i] >> 4) & 15)); StringBuilder h13 = f.h(h12.toString()); h13.append("0123456789ABCDEF".charAt(bArr[i] & 15)); str = h13.toString(); } return str; } public String getImageHash() { return this.mImageHash; } public synchronized void recreate(int i, int i3, int i12, Bitmap bitmap) { byte[] bytes; byte[] bytes2; Bitmap bitmap2 = this.mCached; if (!(bitmap2 != null && bitmap2.getWidth() == i && this.mCached.getHeight() == i3)) { try { this.mCached = Bitmap.createBitmap(i, i3, Bitmap.Config.RGB_565); } catch (OutOfMemoryError unused) { this.mCached = null; } Bitmap bitmap3 = this.mCached; if (bitmap3 != null) { bitmap3.setDensity(i12); } } if (this.mCached != null) { new Canvas(this.mCached).drawBitmap(bitmap, i.f36333a, i.f36333a, this.mPaint); try { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); this.mCached.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream); byte[] byteArray = byteArrayOutputStream.toByteArray(); String lastWebNodeMsg = WebNodesManager.getInstance().getLastWebNodeMsg(); if (!TextUtils.isEmpty(lastWebNodeMsg) && (bytes2 = lastWebNodeMsg.getBytes()) != null && bytes2.length > 0) { byteArray = concat(byteArray, bytes2); } String lastDebugInfo = VisualizedAutoTrackService.getInstance().getLastDebugInfo(); if (!TextUtils.isEmpty(lastDebugInfo) && (bytes = lastDebugInfo.getBytes()) != null && bytes.length > 0) { byteArray = concat(byteArray, bytes); } this.mImageHash = toHex(MessageDigest.getInstance("MD5").digest(byteArray)); } catch (Exception e) { SALog.i("SA.Snapshot", "CachedBitmap.recreate;Create image_hash error=" + e); } } } public synchronized void writeBitmapJSON(Bitmap.CompressFormat compressFormat, int i, OutputStream outputStream) throws IOException { Bitmap bitmap = this.mCached; if (!(bitmap == null || bitmap.getWidth() == 0)) { if (this.mCached.getHeight() != 0) { outputStream.write(34); Base64OutputStream base64OutputStream = new Base64OutputStream(outputStream, 2); this.mCached.compress(Bitmap.CompressFormat.PNG, 100, base64OutputStream); base64OutputStream.flush(); outputStream.write(34); } } outputStream.write("null".getBytes()); } } @SuppressLint({"NewApi"}) public static class ClassNameCache extends LruCache<Class<?>, String> { public ClassNameCache(int i) { super(i); } public String create(Class<?> cls) { return cls.getCanonicalName(); } } public static class RootViewFinder implements Callable<List<RootViewInfo>> { private final CachedBitmap mCachedBitmap = new CachedBitmap(); private final int mClientDensity = 160; private final List<RootViewInfo> mRootViews = new ArrayList(); private void scaleBitmap(RootViewInfo rootViewInfo, Bitmap bitmap) { float f = 1.0f; if (bitmap != null) { int density = bitmap.getDensity(); if (density != 0) { f = 160.0f / ((float) density); } int width = bitmap.getWidth(); int height = bitmap.getHeight(); int width2 = (int) (((double) (((float) bitmap.getWidth()) * f)) + 0.5d); int height2 = (int) (((double) (((float) bitmap.getHeight()) * f)) + 0.5d); if (width > 0 && height > 0 && width2 > 0 && height2 > 0) { this.mCachedBitmap.recreate(width2, height2, 160, bitmap); } } rootViewInfo.scale = f; rootViewInfo.screenshot = this.mCachedBitmap; } public Bitmap mergeViewLayers(View[] viewArr, RootViewInfo rootViewInfo) { int width = rootViewInfo.rootView.getWidth(); int height = rootViewInfo.rootView.getHeight(); if (width == 0 || height == 0) { int[] deviceSize = DeviceUtils.getDeviceSize(SensorsDataAPI.sharedInstance().getContext()); width = deviceSize[0]; height = deviceSize[1]; if (width == 0 || height == 0) { return null; } } Bitmap createBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); SoftWareCanvas softWareCanvas = new SoftWareCanvas(createBitmap); int[] iArr = new int[2]; boolean z = ViewUtil.getMainWindowCount(viewArr) > 1; WindowHelper.init(); ViewUtil.invalidateLayerTypeView(viewArr); boolean z4 = false; for (View view : viewArr) { if (view.getVisibility() == 0 && view.getWidth() != 0 && view.getHeight() != 0 && ViewUtil.isWindowNeedTraverse(view, WindowHelper.getWindowPrefix(view), z)) { softWareCanvas.save(); if (!WindowHelper.isMainWindow(view)) { view.getLocationOnScreen(iArr); softWareCanvas.translate((float) iArr[0], (float) iArr[1]); if (WindowHelper.isDialogOrPopupWindow(view) && !z4) { Paint paint = new Paint(); paint.setColor(-1610612736); softWareCanvas.drawRect(-((float) iArr[0]), -((float) iArr[1]), (float) softWareCanvas.getWidth(), (float) softWareCanvas.getHeight(), paint); z4 = true; } } view.draw(softWareCanvas); softWareCanvas.restore(); softWareCanvas.destroy(); } } return createBitmap; } @Override // java.util.concurrent.Callable public List<RootViewInfo> call() throws Exception { this.mRootViews.clear(); Activity foregroundActivity = AppStateManager.getInstance().getForegroundActivity(); if (foregroundActivity != null) { JSONObject buildTitleAndScreenName = AopUtil.buildTitleAndScreenName(foregroundActivity); VisualUtil.mergeRnScreenNameAndTitle(buildTitleAndScreenName); String optString = buildTitleAndScreenName.optString("$screen_name"); String optString2 = buildTitleAndScreenName.optString("$title"); Window window = foregroundActivity.getWindow(); Bitmap bitmap = null; View rootView = (window == null || !window.isActive()) ? null : window.getDecorView().getRootView(); if (rootView == null) { return this.mRootViews; } RootViewInfo rootViewInfo = new RootViewInfo(optString, optString2, rootView); View[] sortedWindowViews = WindowHelper.getSortedWindowViews(); if (sortedWindowViews != null && sortedWindowViews.length > 0) { bitmap = mergeViewLayers(sortedWindowViews, rootViewInfo); for (View view : sortedWindowViews) { if (view.getWindowVisibility() == 0 && view.getVisibility() == 0 && view.getWidth() != 0 && view.getHeight() != 0 && !TextUtils.equals(WindowHelper.getWindowPrefix(view), WindowHelper.getMainWindowPrefix())) { RootViewInfo rootViewInfo2 = new RootViewInfo(optString, optString2, view.getRootView()); scaleBitmap(rootViewInfo2, bitmap); this.mRootViews.add(rootViewInfo2); } } } if (this.mRootViews.size() == 0) { scaleBitmap(rootViewInfo, bitmap); this.mRootViews.add(rootViewInfo); } } return this.mRootViews; } } public static class RootViewInfo { public final String activityTitle; public final View rootView; public float scale = 1.0f; public final String screenName; public CachedBitmap screenshot; public RootViewInfo(String str, String str2, View view) { this.screenName = str; this.activityTitle = str2; this.rootView = view; } } public ViewSnapshot(List<PropertyDescription> list, ResourceIds resourceIds) { this.mProperties = list; this.mResourceIds = resourceIds; this.mMainThreadHandler = new Handler(Looper.getMainLooper()); this.mRootViewFinder = new RootViewFinder(); this.mClassnameCache = new ClassNameCache(MotionEventCompat.ACTION_MASK); } private void addProperties(JsonWriter jsonWriter, View view) throws IOException { Caller caller; Object applyMethod; Class<?> cls = view.getClass(); for (PropertyDescription propertyDescription : this.mProperties) { if (!(!propertyDescription.targetClass.isAssignableFrom(cls) || (caller = propertyDescription.accessor) == null || (applyMethod = caller.applyMethod(view)) == null)) { if (applyMethod instanceof Number) { jsonWriter.name(propertyDescription.name).value((Number) applyMethod); } else if (applyMethod instanceof Boolean) { boolean booleanValue = ((Boolean) applyMethod).booleanValue(); if (TextUtils.equals("clickable", propertyDescription.name)) { if (VisualUtil.isSupportClick(view)) { booleanValue = true; } else if (VisualUtil.isForbiddenClick(view)) { booleanValue = false; } } jsonWriter.name(propertyDescription.name).value(booleanValue); } else if (applyMethod instanceof ColorStateList) { jsonWriter.name(propertyDescription.name).value(Integer.valueOf(((ColorStateList) applyMethod).getDefaultColor())); } else if (applyMethod instanceof Drawable) { Drawable drawable = (Drawable) applyMethod; Rect bounds = drawable.getBounds(); jsonWriter.name(propertyDescription.name); jsonWriter.beginObject(); jsonWriter.name("classes"); jsonWriter.beginArray(); for (Class<?> cls2 = drawable.getClass(); cls2 != Object.class; cls2 = cls2.getSuperclass()) { jsonWriter.value(cls2.getCanonicalName()); } jsonWriter.endArray(); jsonWriter.name("dimensions"); jsonWriter.beginObject(); jsonWriter.name("left").value((long) bounds.left); jsonWriter.name("right").value((long) bounds.right); jsonWriter.name("top").value((long) bounds.top); jsonWriter.name("bottom").value((long) bounds.bottom); jsonWriter.endObject(); if (drawable instanceof ColorDrawable) { jsonWriter.name("color").value((long) ((ColorDrawable) drawable).getColor()); } jsonWriter.endObject(); } else { jsonWriter.name(propertyDescription.name).value(applyMethod.toString()); } } } } private String getResName(View view) { int id2 = view.getId(); if (-1 == id2) { return null; } return this.mResourceIds.nameForId(id2); } private void getVisibleRect(View view, Rect rect, boolean z) { if (z) { view.getGlobalVisibleRect(rect); return; } int[] iArr = new int[2]; view.getLocationOnScreen(iArr); view.getLocalVisibleRect(rect); rect.offset(iArr[0], iArr[1]); } private boolean isSnapShotUpdated(String str, StringBuilder sb2) { boolean z = !TextUtils.equals(str, sb2) || WebNodesManager.getInstance().hasH5AlertInfo(); if (sb2 != null) { sb2.delete(0, sb2.length()).append(str); } return z; } private void mergeWebViewNodes(JsonWriter jsonWriter, WebNode webNode, View view, float f) { try { jsonWriter.beginObject(); JsonWriter name = jsonWriter.name("hashCode"); name.value(webNode.getId() + view.hashCode()); long j = 0; jsonWriter.name("index").value(0L); if (!TextUtils.isEmpty(webNode.get$element_selector())) { jsonWriter.name("element_selector").value(webNode.get$element_selector()); } if (!TextUtils.isEmpty(webNode.get$element_content())) { jsonWriter.name("element_content").value(webNode.get$element_content()); } JsonWriter name2 = jsonWriter.name("element_level"); SnapInfo snapInfo = this.mSnapInfo; int i = snapInfo.elementLevel + 1; snapInfo.elementLevel = i; name2.value((long) i); jsonWriter.name("h5_title").value(webNode.get$title()); if (f == i.f36333a) { f = webNode.getScale(); } jsonWriter.name("left").value((double) (webNode.getLeft() * f)); jsonWriter.name("top").value((double) (webNode.getTop() * f)); jsonWriter.name("width").value((long) ((int) (webNode.getWidth() * f))); jsonWriter.name("height").value((long) ((int) (webNode.getHeight() * f))); jsonWriter.name("scrollX").value(0L); jsonWriter.name("scrollY").value(0L); boolean z = webNode.getOriginTop() * f <= ((float) view.getHeight()) && webNode.getOriginLeft() * f <= ((float) view.getWidth()); JsonWriter name3 = jsonWriter.name("visibility"); if (!webNode.isVisibility() || !z) { j = 8; } name3.value(j); jsonWriter.name(PushConstants.WEB_URL).value(webNode.get$url()); jsonWriter.name("clickable").value(webNode.isEnable_click()); jsonWriter.name("importantForAccessibility").value(true); jsonWriter.name("is_h5").value(true); jsonWriter.name("is_list_view").value(webNode.isIs_list_view()); jsonWriter.name("element_path").value(webNode.get$element_path()); jsonWriter.name(PushConstants.SUB_TAGS_STATUS_NAME).value(webNode.getTagName()); if (!TextUtils.isEmpty(webNode.get$element_position())) { jsonWriter.name("element_position").value(webNode.get$element_position()); } this.mSnapInfo.webLibVersion = webNode.getLib_version(); jsonWriter.name("list_selector").value(webNode.getList_selector()); jsonWriter.name("classes"); jsonWriter.beginArray(); jsonWriter.value(webNode.getTagName()); Class<?> cls = view.getClass(); do { jsonWriter.value(cls.getCanonicalName()); cls = cls.getSuperclass(); if (cls == Object.class) { break; } } while (cls != null); jsonWriter.endArray(); List<String> subelements = webNode.getSubelements(); if (subelements != null && subelements.size() > 0) { jsonWriter.name("subviews"); jsonWriter.beginArray(); Iterator<String> it2 = subelements.iterator(); while (it2.hasNext()) { jsonWriter.value(it2.next() + view.hashCode()); } jsonWriter.endArray(); } jsonWriter.endObject(); } catch (Exception e) { SALog.printStackTrace(e); } } private void reset() { this.mSnapInfo = new SnapInfo(); ViewUtil.clear(); } private void snapshotView(JsonWriter jsonWriter, final View view, int i) throws IOException { if (ViewUtil.isViewSelfVisible(view)) { ArrayList<String> arrayList = null; int i3 = this.mSnapInfo.elementLevel; if (ViewUtil.instanceOfWebView(view)) { this.mSnapInfo.isWebView = true; final CountDownLatch countDownLatch = new CountDownLatch(1); try { view.post(new Runnable() { /* class com.sensorsdata.analytics.android.sdk.visual.ViewSnapshot.AnonymousClass1 */ public void run() { String str = (String) ReflectUtil.callMethod(view, "getUrl", new Object[0]); if (!TextUtils.isEmpty(str)) { ViewSnapshot.this.mSnapInfo.webViewUrl = str; Float f = (Float) ReflectUtil.callMethod(view, "getScale", new Object[0]); if (f != null) { ViewSnapshot.this.mSnapInfo.webViewScale = f.floatValue(); } countDownLatch.countDown(); SensorsDataAutoTrackHelper.loadUrl(view, "javascript:window.sensorsdata_app_call_js('visualized')"); return; } countDownLatch.countDown(); } }); } catch (Exception e) { SALog.printStackTrace(e); } try { countDownLatch.await(500, TimeUnit.MILLISECONDS); } catch (InterruptedException e6) { SALog.printStackTrace(e6); } StringBuilder h12 = f.h("WebView url: "); h12.append(this.mSnapInfo.webViewUrl); SALog.i("SA.Snapshot", h12.toString()); if (!TextUtils.isEmpty(this.mSnapInfo.webViewUrl)) { WebNodeInfo webNodes = WebNodesManager.getInstance().getWebNodes(this.mSnapInfo.webViewUrl); if (webNodes == null) { if (this.mAlertRunnable == null) { this.mAlertRunnable = new AlertRunnable(this.mSnapInfo.webViewUrl); } Dispatcher.getInstance().postDelayed(this.mAlertRunnable, 5000); } else if (webNodes.getStatus() == WebNodeInfo.Status.SUCCESS) { List<WebNode> webNodes2 = webNodes.getWebNodes(); if (webNodes2 != null && webNodes2.size() > 0) { arrayList = new ArrayList(); for (WebNode webNode : webNodes2) { mergeWebViewNodes(jsonWriter, webNode, view, this.mSnapInfo.webViewScale); if (webNode.isRootView()) { arrayList.add(webNode.getId() + view.hashCode()); } } } } else if (webNodes.getStatus() == WebNodeInfo.Status.FAILURE) { this.mSnapInfo.alertInfos = webNodes.getAlertInfos(); } } } jsonWriter.beginObject(); jsonWriter.name("hashCode").value((long) view.hashCode()); jsonWriter.name("id").value((long) view.getId()); jsonWriter.name("index").value((long) VisualUtil.getChildIndex(view.getParent(), view)); if (ViewUtil.instanceOfWebView(view)) { jsonWriter.name("element_level").value((long) i3); } else { JsonWriter name = jsonWriter.name("element_level"); SnapInfo snapInfo = this.mSnapInfo; int i12 = snapInfo.elementLevel + 1; snapInfo.elementLevel = i12; name.value((long) i12); } jsonWriter.name("element_selector").value(ViewUtil.getElementSelector(view)); JSONObject screenNameAndTitle = VisualUtil.getScreenNameAndTitle(view, this.mSnapInfo); if (screenNameAndTitle != null) { String optString = screenNameAndTitle.optString("$screen_name"); String optString2 = screenNameAndTitle.optString("$title"); if (!TextUtils.isEmpty(optString)) { jsonWriter.name("screen_name").value(optString); } if (!TextUtils.isEmpty(optString2)) { jsonWriter.name(PushConstants.TITLE).value(optString2); } } ViewNode viewNode = ViewUtil.getViewNode(view, i, true); if (viewNode != null) { if (!TextUtils.isEmpty(viewNode.getViewPath())) { jsonWriter.name("element_path").value(viewNode.getViewPath()); } if (!TextUtils.isEmpty(viewNode.getViewPosition())) { jsonWriter.name("element_position").value(viewNode.getViewPosition()); } if (!TextUtils.isEmpty(viewNode.getViewContent()) && VisualUtil.isSupportElementContent(view)) { jsonWriter.name("element_content").value(viewNode.getViewContent()); } jsonWriter.name("is_list_view").value(viewNode.isListView()); } jsonWriter.name("sa_id_name").value(getResName(view)); try { String str = (String) view.getTag(R.id.sensors_analytics_tag_view_id); if (!TextUtils.isEmpty(str)) { jsonWriter.name("sa_id_name").value(str); } } catch (Exception e12) { SALog.printStackTrace(e12); } if (WindowHelper.isMainWindow(view.getRootView())) { jsonWriter.name("top").value((long) view.getTop()); jsonWriter.name("left").value((long) view.getLeft()); jsonWriter.name("width").value((long) view.getWidth()); jsonWriter.name("height").value((long) view.getHeight()); } else if (WindowHelper.isDecorView(view.getClass())) { DisplayMetrics displayMetrics = view.getContext().getResources().getDisplayMetrics(); int i13 = displayMetrics.widthPixels; int i14 = displayMetrics.heightPixels; jsonWriter.name("top").value((long) view.getTop()); jsonWriter.name("left").value((long) view.getLeft()); jsonWriter.name("width").value((long) i13); jsonWriter.name("height").value((long) i14); } else { ViewParent parent = view.getParent(); if (parent == null || !WindowHelper.isDecorView(parent.getClass())) { jsonWriter.name("top").value((long) view.getTop()); jsonWriter.name("left").value((long) view.getLeft()); jsonWriter.name("width").value((long) view.getWidth()); jsonWriter.name("height").value((long) view.getHeight()); } else { Rect rect = new Rect(); getVisibleRect(view, rect, false); jsonWriter.name("top").value((long) rect.top); jsonWriter.name("left").value((long) rect.left); jsonWriter.name("width").value((long) rect.width()); jsonWriter.name("height").value((long) rect.height()); } } int scrollX = view.getScrollX(); if ((view instanceof TextView) && ((TextView) view).getMaxLines() == 1) { scrollX = 0; } if (ViewUtil.instanceOfX5WebView(view)) { try { jsonWriter.name("scrollX").value((Integer) ReflectUtil.callMethod(view, "getWebScrollX", new Object[0])); jsonWriter.name("scrollY").value((Integer) ReflectUtil.callMethod(view, "getWebScrollY", new Object[0])); } catch (IOException e13) { SALog.printStackTrace(e13); } } else { jsonWriter.name("scrollX").value((long) scrollX); jsonWriter.name("scrollY").value((long) view.getScrollY()); } jsonWriter.name("visibility").value((long) VisualUtil.getVisibility(view)); float translationX = view.getTranslationX(); float translationY = view.getTranslationY(); jsonWriter.name("translationX").value((double) translationX); jsonWriter.name("translationY").value((double) translationY); jsonWriter.name("classes"); jsonWriter.beginArray(); Class<?> cls = view.getClass(); do { jsonWriter.value((String) this.mClassnameCache.get(cls)); cls = cls.getSuperclass(); if (cls == Object.class) { break; } } while (cls != null); jsonWriter.endArray(); addProperties(jsonWriter, view); ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); if (layoutParams instanceof RelativeLayout.LayoutParams) { int[] rules = ((RelativeLayout.LayoutParams) layoutParams).getRules(); jsonWriter.name("layoutRules"); jsonWriter.beginArray(); for (int i15 : rules) { jsonWriter.value((long) i15); } jsonWriter.endArray(); } jsonWriter.name("subviews"); jsonWriter.beginArray(); if (arrayList != null && arrayList.size() > 0) { for (String str2 : arrayList) { jsonWriter.value(str2); } } else if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; int childCount = viewGroup.getChildCount(); for (int i16 = 0; i16 < childCount; i16++) { View childAt = viewGroup.getChildAt(i16); if (childAt != null) { jsonWriter.value((long) childAt.hashCode()); } } } jsonWriter.endArray(); jsonWriter.endObject(); } if (view instanceof ViewGroup) { ViewGroup viewGroup2 = (ViewGroup) view; int childCount2 = viewGroup2.getChildCount(); for (int i17 = 0; i17 < childCount2; i17++) { View childAt2 = viewGroup2.getChildAt(i17); if (childAt2 != null) { snapshotView(jsonWriter, childAt2, i17); } } } } private void snapshotViewHierarchy(JsonWriter jsonWriter, View view) throws IOException { reset(); jsonWriter.beginArray(); snapshotView(jsonWriter, view, 0); jsonWriter.endArray(); WebNodesManager.getInstance().setHasWebView(this.mSnapInfo.isWebView); } public synchronized SnapInfo snapshots(UIThreadSet<Activity> uIThreadSet, OutputStream outputStream, StringBuilder sb2) throws IOException { SnapInfo snapInfo; CachedBitmap cachedBitmap; FutureTask futureTask = new FutureTask(this.mRootViewFinder); this.mMainThreadHandler.post(futureTask); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); List emptyList = Collections.emptyList(); outputStreamWriter.write("["); try { emptyList = (List) futureTask.get(1, TimeUnit.SECONDS); } catch (InterruptedException e) { SALog.i("SA.Snapshot", "Screenshot interrupted, no screenshot will be sent.", e); } catch (TimeoutException e6) { SALog.i("SA.Snapshot", "Screenshot took more than 1 second to be scheduled and executed. No screenshot will be sent.", e6); } catch (ExecutionException e12) { SALog.i("SA.Snapshot", "Exception thrown during screenshot attempt", e12); } int size = emptyList.size(); String str = null; String str2 = null; for (int i = 0; i < size; i++) { RootViewInfo rootViewInfo = (RootViewInfo) emptyList.get(i); if (i > 0) { outputStreamWriter.write(","); } if (rootViewInfo == null || (cachedBitmap = rootViewInfo.screenshot) == null || (!isSnapShotUpdated(cachedBitmap.getImageHash(), sb2) && i <= 0)) { outputStreamWriter.write("{}"); } else { outputStreamWriter.write("{"); outputStreamWriter.write("\"activity\":"); str = rootViewInfo.screenName; str2 = rootViewInfo.activityTitle; outputStreamWriter.write(JSONObject.quote(str)); outputStreamWriter.write(","); outputStreamWriter.write("\"scale\":"); outputStreamWriter.write(String.format("%s", Float.valueOf(rootViewInfo.scale))); outputStreamWriter.write(","); outputStreamWriter.write("\"serialized_objects\":"); JsonWriter jsonWriter = new JsonWriter(outputStreamWriter); jsonWriter.beginObject(); jsonWriter.name("rootObject").value((long) rootViewInfo.rootView.hashCode()); jsonWriter.name("objects"); snapshotViewHierarchy(jsonWriter, rootViewInfo.rootView); jsonWriter.endObject(); jsonWriter.flush(); outputStreamWriter.write(","); outputStreamWriter.write("\"image_hash\":"); outputStreamWriter.write(JSONObject.quote(rootViewInfo.screenshot.getImageHash())); outputStreamWriter.write(","); outputStreamWriter.write("\"screenshot\":"); outputStreamWriter.flush(); rootViewInfo.screenshot.writeBitmapJSON(Bitmap.CompressFormat.PNG, 70, outputStream); outputStreamWriter.write("}"); } } outputStreamWriter.write("]"); outputStreamWriter.flush(); snapInfo = this.mSnapInfo; snapInfo.screenName = str; snapInfo.activityTitle = str2; return snapInfo; } }