Error in onPixelCopyFinished after updrading to 6000.0.11f1

I might try that then.
Could that exception I uploaded in the previous response be related to the same issue?
It’s our #1 crash, but it happens on 2 of 5 games only (which “surprisingly” those games are played with low end phones)

Thanks!

That exception doesn’t look like the same stacktrace, so it might be a different thing. I’ll investigate if there is anyone else reporting a similar issue.

Same here, a lot of my crashes caused by the same “bug” since upgrading to Unity6, Unfortunately couldn’t reproduce locally, however I think it could be something related to threading, some NOT ALL of the crashes show this line:

Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

And some of them have mentions the calling thread
eg;

Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. Expected: main Calling: PlaceHolderView

I tried to dig more by exporting Android Project, and trying to find something related to the [PlaceHolderView], The only thing I found is that the code change is relatively new (Unity 2023) maybe, not sure though, but the class which call this method is not the same, compared to Unity2022. I tried to create a test track with the new “Game Activity” to check if its related in any way, but I could because the game crashed immediately.

Here is a sample stack trace

Exception java.lang.Error: FATAL EXCEPTION [PlaceHolderView]
Unity version     : 6000.0.12f1
Device model      : Xiaomi 2210129SG
Device fingerprint: Xiaomi/ziyi_global/ziyi:12/SKQ1.220303.001/V14.0.1.0.SLLMIXM:user/release-keys
CPU supported ABI : [arm64-v8a, armeabi-v7a, armeabi]
Build Type        : Release
Scripting Backend : IL2CPP
Libs loaded from  : lib/arm64
Strip Engine Code : true

Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
  at android.view.ViewRootImpl.checkThread (ViewRootImpl.java:9948)
  at android.view.ViewRootImpl.invalidateChildInParent (ViewRootImpl.java:2001)
  at android.view.ViewGroup.invalidateChild (ViewGroup.java:6180)
  at android.view.View.invalidateInternal (View.java:19161)
  at android.view.View.invalidate (View.java:19091)
  at android.view.View.invalidateDrawable (View.java:23835)
  at android.graphics.drawable.Drawable.invalidateSelf (Drawable.java:492)
  at android.graphics.drawable.Drawable.setVisible (Drawable.java:940)
  at android.graphics.drawable.LayerDrawable.setVisible (LayerDrawable.java:1333)
  at android.view.View.setBackgroundDrawable (View.java:24427)
  at android.view.View.setBackground (View.java:24403)
  at com.unity3d.player.C.onPixelCopyFinished
  at android.view.PixelCopy$1.run (PixelCopy.java:191)
  at android.os.Handler.handleCallback (Handler.java:938)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:211)
  at android.os.Looper.loop (Looper.java:300)
  at android.os.HandlerThread.run (HandlerThread.java:67)

@just9 I tried turning multi-threading rendering off and also managed to install via GameActivity, I thought the same as you but I still had the same issue, and as @mcolombo has stated I also had it across multiple devices and specs.

Its a Java thread, not from C++/C# Side, so Multi-threaded rendering has no effect here I believe.
This crash only happen on Android devices, the stack trace is all about Java and Android.
And as you stated before:

Hi, I also don’t get the error in 2022.3.x ( once I down graded and uploaded a new version ), I’ve had a few games out now for a while ( basically 2 weeks ) and that error has not cropped up once.

This has nothing to do with low-end devices or Specs, It was already working as expected in previous unity versions even on the low-end devices.

Apparently Unity6 has different structure for the “unity-classes.jar” see Gradle for Android.
By examining this file, even though its compiled, its obvious how the code handling onPixelCopyFinished is different from previous versions, Now its involving threads,
I think it is ok to share it here, its compiled anyway

Here is the Unity6 way of making this request,
Look for PixelCopy.request, note that onPixelCopyFinished is some type of callback for this request according to android’s official docs: PixelCopy

Unity6

final class D extends View {
   Bitmap a;

   D(Context var1) {
      super(var1);
   }

   public final void a(SurfaceView var1) {
      x.Log(3, "PersistentUnitySurface.PlaceholderView.Copy: " + var1 + " Width " + var1.getWidth() + "  Height " + var1.getHeight());
      this.a = Bitmap.createBitmap(var1.getWidth(), var1.getHeight(), Config.ARGB_8888);
      HandlerThread var2;
      HandlerThread var10000 = var2 = new HandlerThread;
      var10000.<init>("PlaceHolderView");
      var10000.start();
      Semaphore var3;
      Semaphore var7 = var3 = new Semaphore;
      var3.<init>(0);
      Bitmap var10002 = this.a;
      C var10003 = new C(this, var3);
      Handler var6;
      var6 = new Handler.<init>(var2.getLooper());
      PixelCopy.request(var1, var10002, var10003, var6);
      long var10001 = 2000L;

      label25: {
         InterruptedException var8;
         label29: {
            boolean var9;
            boolean var10;
            try {
               var9 = var7.tryAcquire(var10001, TimeUnit.MILLISECONDS);
            } catch (InterruptedException var5) {
               var8 = var5;
               var10 = false;
               break label29;
            }

            if (var9) {
               break label25;
            }

            byte var11 = 5;

            try {
               x.Log(var11, "Timeout while copying surface view.");
               break label25;
            } catch (InterruptedException var4) {
               var8 = var4;
               var10 = false;
            }
         }

         x.Log(6, var8.getMessage());
      }

      var2.quitSafely();
   }
}

And here is Unity 2023’s one:

class P implements Callback {
   // $FF: synthetic field
   final Q a;

   P(Q var1) {
      this.a = var1;
   }

   public void surfaceCreated(SurfaceHolder var1) {
      this.a.b.updateGLDisplay(0, var1.getSurface());
      Q var3;
      w var5;
      w var10000 = var5 = (var3 = this.a).c;
      UnityPlayer var4 = var3.b;
      v var2;
      if ((var2 = var10000.b) != null && var2.getParent() == null) {
         var4.addView(var5.b);
         var4.bringChildToFront(var5.b);
      }

   }

   public void surfaceChanged(SurfaceHolder var1, int var2, int var3, int var4) {
      this.a.b.updateGLDisplay(0, var1.getSurface());
      this.a.b.sendSurfaceChangedEvent();
   }

   public void surfaceDestroyed(SurfaceHolder var1) {
      w var2;
      Q var4;
      w var10000 = var2 = (var4 = this.a).c;
      a var5 = var4.a;
      var10000.getClass();
      if (PlatformSupport.NOUGAT_SUPPORT && var2.a != null) {
         if (var2.b == null) {
            v var3;
            var3 = new v.<init>(var2, var2.a);
            var2.b = var3;
         }

         a var9 = var5;
         v var7;
         v var10001 = var7 = var2.b;
         var7.getClass();
         Bitmap var6;
         var10001.a = var6 = Bitmap.createBitmap(var5.getWidth(), var5.getHeight(), Config.ARGB_8888);
         Bitmap var10 = var6;
         Handler var8;
         var8 = new Handler.<init>(Looper.getMainLooper());
         PixelCopy.request(var9, var10, var7, var8);
      }

      this.a.b.updateGLDisplay(0, (Surface)null);
   }
}

Note that it could be the same implementation of the old versions were the old version have other name for “PlaceHolderView” thread initialized in another class some were, its hard to tell without having the source code, but for now, I believe the “PlaceHolderView” thread is trying to call something on the “android.view” instead of the “main” thread.

Hi Everyone,

I already submitted a bug for this issue, and @manugil is looking into it.
In fact, he stated on the bug that he has a clear idea of what could be happening, so fingers crossed a fix will be ready soon.

Nevertheless, he suggested trying Unity 6000.0.5f1, which I did and uploaded an update yesterday.
For the moment, the bug HAS NOT SHOWN. Which is very very promising. So I will be updating more games into this version until the fix is ready.

This would suggest that the bug has appeared in Unity 7f1.

Just to let you know I tried this and for the moment is working. The crash has not shown.

2 Likes

Thank you. I have released it by changing the version to 6000.0.5f1. One more thing to add, after changing to Unity 6 (6000.0.9f1), there was overheating. This issue has also been fixed.

I can confirm that the crash disappears on 6000.0.5f1. Tried it on 3 games.

1 Like

This is so weird. I also have this error. I’m in Unity 6 15f1. However, I had uploaded more than 20 aab then after I had reduced my bundle from 30 bundles into 5 bundles of assetpack, it cause crash.

We are working on a fix for UUM-79451, we’ll keep you informed regarding any progress on the case!

1 Like

Can we get fast fix for this issue? It has raised the crash rate on playstore console above 1% in my published apps, migrating my projects to 6000.0.5f1 is a no go for me since 6000.0.5f1 has regressions in other areas which are even worse. I will soon most like be redflaged by playstore on vitals with this issue

Yes, 5f1 is raising the crash rate as well, despite not showing the error on this thread.
We will have to wait for @manugil for a fix.

1 Like

The crash has now been fixed for 6000.0.20f1+ (UUM-70451).

1 Like