{ "id": "154124", "key": "TIMOB-20206", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "18928", "name": "Release 6.0.2", "archived": false, "released": true, "releaseDate": "2017-02-27" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2016-09-06T06:00:49.000+0000", "created": "2016-01-05T17:56:04.000+0000", "priority": { "name": "Critical", "id": "1" }, "labels": [], "versions": [], "issuelinks": [ { "id": "54068", "type": { "id": "10002", "name": "Duplicate", "inward": "is duplicated by", "outward": "duplicates" }, "inwardIssue": { "id": "99097", "key": "TIMOB-10508", "fields": { "summary": "Android: java.lang.IllegalStateException: Ambiguous Z-Order", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "Low", "id": "4" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } } ], "assignee": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "updated": "2017-01-31T18:30:59.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "I'm writing in from the Android team. The \"N\" release of Android is moving over to using OpenJdk as its implementation for java.* libraries. One of the issues that came up in our testing a crash that looks like this : \r\n\r\njava.lang.IllegalStateException: Ambiguous Z-Order\r\n at org.appcelerator.titanium.view.TiCompositeLayout$1.compare(TiCompositeLayout.java:164)\r\n at org.appcelerator.titanium.view.TiCompositeLayout$1.compare(TiCompositeLayout.java:127)\r\n at java.util.TreeMap.compare(TreeMap.java:1190)\r\n at java.util.TreeMap.put(TreeMap.java:532)\r\n at java.util.TreeSet.add(TreeSet.java:255)\r\n at org.appcelerator.titanium.view.TiCompositeLayout.onLayout(TiCompositeLayout.java:491)\r\n at android.view.View.layout(View.java:16945)\r\n at android.view.ViewGroup.layout(ViewGroup.java:5516)\r\n\r\nThe issue here is their Comparator expects that its arguments are never equal (i.e, none of its code paths return 0). That seems pretty brittle and contrary to the documented contract.\r\n\r\nIt fails on OpenJdk because of this snippet of code in TreeMap#put :\r\n\r\n TreeMapEntry t = root;\r\n if (t == null) {\r\n compare(key, key); // type (and possibly null) check <--- [BUG HERE] we're deliberately comparing a view with itself for the side effects : null & type check\r\n .....\r\n\r\nI will put in a workaround for the upcoming release, but It will be reverted in a future Android release.\r\n", "attachment": [], "flagged": false, "summary": "Android : TiCompositeLayout's viewSorter does not abide by Comparator's contract", "creator": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "subtasks": [], "reporter": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "environment": null, "closedSprints": [ { "id": 704, "state": "closed", "name": "2016 Sprint 18 SDK", "startDate": "2016-08-27T00:18:36.960Z", "endDate": "2016-09-10T00:18:00.000Z", "completeDate": "2016-09-09T20:26:13.865Z", "originBoardId": 114 } ], "comment": { "comments": [ { "id": "373975", "author": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "body": "[~kamath.narayan@gmail.com] Thanks for the ticket!\r\n\r\nIs this something that only occurs with \"N\" (with the OpenJDK implementation)?", "updateAuthor": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "created": "2016-01-07T03:55:05.000+0000", "updated": "2016-01-07T03:55:05.000+0000" }, { "id": "373990", "author": { "name": "bdc", "key": "bdc", "displayName": "Brian Carlstrom", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Yes, this is new with the OpenJDK TreeMap implementation in N", "updateAuthor": { "name": "bdc", "key": "bdc", "displayName": "Brian Carlstrom", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2016-01-07T07:07:38.000+0000", "updated": "2016-01-07T07:07:38.000+0000" }, { "id": "380508", "author": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "body": "Hello all - have you had any luck fixing this issue ? The Android N preview is now public and contains a platform workaround. We would like to remove the workaround at some point, which would leave apps that use this class broken.", "updateAuthor": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "created": "2016-03-23T10:42:25.000+0000", "updated": "2016-03-23T10:42:25.000+0000" }, { "id": "380755", "author": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "body": "[~kamath.narayan@gmail.com] Thanks for the ping. We will be working on this and testing it on N. :)", "updateAuthor": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "created": "2016-03-28T02:41:42.000+0000", "updated": "2016-03-28T02:41:55.000+0000" }, { "id": "393506", "author": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "body": "In the change cited here [1], we have reverted the workaround I mentioned in my earlier comment.\r\n\r\nAll applications using TiCompositeLayout will break in a future android release unless this bug is fixed.\r\n\r\n[1] https://android-review.googlesource.com/#/c/257511/1 ", "updateAuthor": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "created": "2016-08-18T13:57:56.000+0000", "updated": "2016-08-18T13:57:56.000+0000" }, { "id": "393564", "author": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "body": "[~kamath.narayan@gmail.com] Thanks for the update! So basically beyond N will break this?", "updateAuthor": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "created": "2016-08-19T02:28:36.000+0000", "updated": "2016-08-19T02:28:36.000+0000" }, { "id": "393566", "author": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "body": "To refer to https://android-review.googlesource.com/#/c/257511/1/ojluni/src/main/java/java/util/TreeMap.java", "updateAuthor": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "created": "2016-08-19T02:30:04.000+0000", "updated": "2016-08-19T02:30:04.000+0000" }, { "id": "393590", "author": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "body": "hi - yes, that's right.", "updateAuthor": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "created": "2016-08-19T07:49:39.000+0000", "updated": "2016-08-19T07:49:39.000+0000" }, { "id": "393591", "author": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "body": "Thanks for replying! Appreciate it a whole lot.", "updateAuthor": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "created": "2016-08-19T07:53:13.000+0000", "updated": "2016-08-19T07:53:13.000+0000" }, { "id": "394767", "author": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "body": "For ref: http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Comparator.java/?v=source\r\n\r\n{code}\r\n /**\r\n * Compares its two arguments for order. Returns a negative integer,\r\n * zero, or a positive integer as the first argument is less than, equal\r\n * to, or greater than the second.

\r\n *\r\n * In the foregoing description, the notation\r\n * sgn(expression) designates the mathematical\r\n * signum function, which is defined to return one of -1,\r\n * 0, or 1 according to whether the value of\r\n * expression is negative, zero or positive.

\r\n *\r\n * The implementor must ensure that sgn(compare(x, y)) ==\r\n * -sgn(compare(y, x)) for all x and y. (This\r\n * implies that compare(x, y) must throw an exception if and only\r\n * if compare(y, x) throws an exception.)

\r\n *\r\n * The implementor must also ensure that the relation is transitive:\r\n * ((compare(x, y)>0) && (compare(y, z)>0)) implies\r\n * compare(x, z)>0.

\r\n *\r\n * Finally, the implementor must ensure that compare(x, y)==0\r\n * implies that sgn(compare(x, z))==sgn(compare(y, z)) for all\r\n * z.

\r\n *\r\n * It is generally the case, but not strictly required that\r\n * (compare(x, y)==0) == (x.equals(y)). Generally speaking,\r\n * any comparator that violates this condition should clearly indicate\r\n * this fact. The recommended language is \"Note: this comparator\r\n * imposes orderings that are inconsistent with equals.\"\r\n *\r\n * @param o1 the first object to be compared.\r\n * @param o2 the second object to be compared.\r\n * @return a negative integer, zero, or a positive integer as the\r\n * first argument is less than, equal to, or greater than the\r\n * second.\r\n * @throws ClassCastException if the arguments' types prevent them from\r\n * being compared by this comparator.\r\n */\r\n int compare(T o1, T o2);\r\n{code}", "updateAuthor": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "created": "2016-08-30T06:35:00.000+0000", "updated": "2016-08-30T06:35:00.000+0000" }, { "id": "394770", "author": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "body": "PR: https://github.com/appcelerator/titanium_mobile/pull/8287\r\n[~cwilliams] for your review.", "updateAuthor": { "name": "msamah", "key": "msamah", "displayName": "Ashraf Abu", "active": false, "timeZone": "Asia/Singapore" }, "created": "2016-08-30T07:25:10.000+0000", "updated": "2016-08-30T07:26:13.000+0000" }, { "id": "404204", "author": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "updateAuthor": { "name": "kamath.narayan@gmail.com", "key": "kamath.narayan@gmail.com", "displayName": "Narayan K", "active": true, "timeZone": "Europe/London" }, "created": "2017-01-06T10:22:59.000+0000", "updated": "2017-01-06T10:22:59.000+0000" }, { "id": "405356", "author": { "name": "gmathews", "key": "gmathews", "displayName": "Gary Mathews", "active": true, "timeZone": "America/Los_Angeles" }, "body": "6_0_X: https://github.com/appcelerator/titanium_mobile/pull/8793", "updateAuthor": { "name": "gmathews", "key": "gmathews", "displayName": "Gary Mathews", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2017-01-26T04:10:00.000+0000", "updated": "2017-01-26T04:10:00.000+0000" }, { "id": "405864", "author": { "name": "awaldman", "key": "awaldman", "displayName": "Andy Waldman", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Test Tuesday 31st January 2017\r\nENV:\r\nThursday 26th January 2017:\r\nENV: \r\nMacOS:10.12.1 \r\nXCODE: 8.2.1 GM (golden master) \r\nAPPC CLI Core: 6.1.0 \r\nAPPC CLI NPM: 4.2.8 \r\nSDK: 6.0.2.v20170130045621\r\nStudio build: 4.8.1.201612050850 \r\nNPM: 2.15.9 \r\nNode: 4.5.0 \r\nDevice: Google Pixel\r\nAndroid Version: 7.1\r\n\r\nStep 1) Create a new classic app in studio\r\nStep 2) Run the classic app with the latest 6.0.2 build on a android phone with 7.0 or greater\r\nStep 3) Verify that the app does not crash \r\n\r\nAfter completing the steps above i can verify that the fix is ok", "updateAuthor": { "name": "awaldman", "key": "awaldman", "displayName": "Andy Waldman", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2017-01-31T18:22:49.000+0000", "updated": "2017-01-31T18:22:49.000+0000" }, { "id": "405865", "author": { "name": "awaldman", "key": "awaldman", "displayName": "Andy Waldman", "active": true, "timeZone": "America/Los_Angeles" }, "body": "In Addition to the above here is the app.js code i tested to verify this ticket\r\n\r\n{code:java}\r\nvar win = Ti.UI.createWindow({backgroundColor: 'gray'}),\r\n view = Ti.UI.createView({backgroundColor: 'red', width: '66%', height: '66%'});\r\n\r\nwin.add(view);\r\nwin.add(view);\r\n\r\nwin.open();\r\n{code}\r\n", "updateAuthor": { "name": "awaldman", "key": "awaldman", "displayName": "Andy Waldman", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2017-01-31T18:30:59.000+0000", "updated": "2017-01-31T18:30:59.000+0000" } ], "maxResults": 20, "total": 20, "startAt": 0 } } }