ndk
ndk copied to clipboard
[BUG] `surface_control.h` and `*font*.h` contains C++ constructs
Description
I maintain the Rust ndk and ndk-sys crates, and they rely on bindgen to parse C headers.
Unfortunately, while attempting to generate these for the font headers and later surface_control.h Rust's bindgen utility complains that the headers are not valid C (these things only work in C++):
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font.h:102:18: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font.h:124:50: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font.h:194:32: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font.h:204:27: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font.h:218:45: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font.h:232:39: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font.h:265:33: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font.h:280:33: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font.h:295:32: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font_matcher.h:135:1: error: must use 'struct' tag to refer to type 'AFontMatcher'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font_matcher.h:144:27: error: must use 'struct' tag to refer to type 'AFontMatcher'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font_matcher.h:159:9: error: must use 'struct' tag to refer to type 'AFontMatcher'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font_matcher.h:175:9: error: must use 'struct' tag to refer to type 'AFontMatcher'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font_matcher.h:190:9: error: must use 'struct' tag to refer to type 'AFontMatcher'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font_matcher.h:211:1: error: must use 'struct' tag to refer to type 'AFont'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/font_matcher.h:212:15: error: must use 'struct' tag to refer to type 'AFontMatcher'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/surface_control.h:343:57: error: C does not support default arguments
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/surface_control.h:355:48: error: must use 'enum' tag to refer to type 'ADataSpace'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/surface_control.h:379:83: error: expected ')'
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/surface_control.h:378:37: note: to match this '('
Missing struct and enum tags
These are easy enough (but ugly) to work around with typedefs:
typedef enum ADataSpace ADataSpace;
typedef struct AFont AFont;
typedef struct AFontMatcher AFontMatcher;
typedef struct ASystemFontIterator ASystemFontIterator;
Language features we cannot work around
Default function arguments
~/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/surface_control.h:343:57:
void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, AHardwareBuffer* buffer,
int acquire_fence_fd = -1) __INTRODUCED_IN(29);
C++ references instead of pointers
/home/marijn/Android/Sdk/ndk/26.0.10404224/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/surface_control.h:379:83 (and at more places):
void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, const ARect& source,
const ARect& destination, int32_t transform)
__INTRODUCED_IN(29);
Affected versions
r25, r26
Canary version
No response
Host OS
Linux
Host OS version
Arch Linux
Affected ABIs
armeabi-v7a, arm64-v8a, x86, x86_64
Build system
Other (specify below)
Other build system
bindgen on headers only
minSdkVersion
Irrelevant for header codegen
Device API level
No response
Hmm. I'd like to fix this in r26 but that particular component has gotten tricky to update now that rv64 is in the development branch. It isn't a regression in r26, so this may slip to r27. I don't think that would be a problem for your use case because you could just update those projects from the canary anyway. Really you probably don't even need an NDK and could just pull the sysroot from ci.android.com.
(and i guess this is another vote for "we really should get around to setting up the 'check that every header can be included in .c files' test" that comes up every year or so...)
I could even fix the signatures locally to get it to build. Generating from canary might be more worrisome if that includes possibly unstabilized/unfinished APIs?
Generating from the NDK means we have a stable version our userbase can go off of.
Generating from canary might be more worrisome if that includes possibly unstabilized/unfinished APIs?
The data needed to avoid those is there (__attribute__((availability))), but you're probably right that cbindgen doesn't read it.
I don't think we get those passed on, neither do we see the __INTRODUCED_IN(29) even though those would be super useful to automatically generate #[cfg(feature = "api-level-{}")] on the Rust side.
Maybe we can with a custom bindgen callback though.
For most APIs (doesn't work for libc/libm because reasons) you need https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#Weak-symbols-for-API-definitions or the decl will be hidden from cbindgen.
This is not enabled by default because, unless used cautiously, this method is prone to deferring build failures to run-time (and only on older devices, since newer devices will have the API).
It would be helpful for us for similar reasons: if we build-test our NDK high-level wrapper crate against every API version, we can very easily spot mismatches (when a symbol is used in the high-level wrapper without the appropriate cfg-guard).
Note that the same issue appears in the thermal headers as well:
/opt/android-sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/thermal.h:114:53: error: must use 'enum' tag to refer to type 'AThermalStatus'
/opt/android-sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/thermal.h:146:1: error: must use 'enum' tag to refer to type 'AThermalStatus'
panicked at 'Unable to generate bindings: ClangDiagnostic("/opt/android-sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/thermal.h:114:53: error: must use 'enum' tag to refer to type 'AThermalStatus'\n/opt/android-sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/thermal.h:146:1: error: must use 'enum' tag to refer to type 'AThermalStatus'\n")', bindgen-cli/main.rs:52:36
Not sure if you're aware and/or adding a CI process to check that all headers are C-compliant, so mentioning it here.
Not sure if you're aware and/or adding a CI process to check that all headers are C-compliant, so mentioning it here.
We tried, but the build systems we have to work made it quite difficult.
Really you probably don't even need an NDK and could just pull the sysroot from ci.android.com.
On this note, without spawning a totally new issue for a simple question, where can I find what is scheduled to be included in the next (r26c) release? Android 14 added AImageReader_newWithDataSpace() which is necessary to create an ImageReader for an RGB10A2 format. This format is only available in AHARDWAREBUFFER_FORMAT and not in AIMAGE_FORMAT, and only the new API function allows AHARDWAREBUFFER_FORMAT (together with a data space).
I tried looking at cs.android.com but I only only see tags/branches for past releases such as: https://cs.android.com/android/platform/superproject/+/ndk-r26b:prebuilts/ndk/platform/sysroot/usr/include/media/NdkImageReader.h
Can you point me in the right direction?
Looks like the font headers have been fixed, but surface_control.h is still broken even on the latest CI builds. Can I contribute these changes upstream? I have decided to need and write a wrapper for SurfaceControl now, and continuously need to make trivial fixes to this header if I wish to regenerate/update our bindings.
On that note I'm very much inclined to follow @DanAlbert's advice and migrate the ndk-sys crate to NDK CI builds because of all the missing API from the published NDK as pointed out above.
@appujee what is your plan for the https://github.com/android/ndk/labels/rust label? While this issue primarily impacts our ecosystem, the effect is global (headers aren't usable in plain C) and not limited to Rust.
Also notice that while this API takes an ADataSpace (should be enum ADataSpace to be valid C), all other APIs take an int dataSpace.
Which of the two is correct?
Can I contribute these changes upstream?
yes, of course. (whether the owners will take them is of course a slightly different question, but at least at that point you'd be talking to the api owners!)
Which of the two is correct?
i don't think we have any idea. i've forwarded your question to the person who added the api though.
@enh-google thanks! After some fighting with repo all changes are uploaded and live at https://android-review.googlesource.com/c/platform/frameworks/native/+/2897863!
In general I'm struggling a bit with the NDK here. First reported at https://issuetracker.google.com/issues/300602767, there are quite a few inconsistencies in the documentation, and I'd like to have (more) complete (non-)nullability annotations as well as thread safety/threading guarantees for both structures/pointers and callbacks (i.e. is an object internally synchronized? Can it be "moved" to another thread as long as it is not accessed concurrently? Will a callback be called on the current thread, or on one other thread? Or on multiple threads, possibly concurrently, hence requiring synchronization)? There was some activity and response initially, but as I started reporting more inconsistencies (with a general "please check the whole file as I cannot report every line"), activity died down.
In general I'm struggling a bit with the NDK here.
it's a classic "your org chart is showing" problem... you want to talk to a person/group that doesn't exist. what does exist is "us", who own the toolchain and include a sysroot, and then a multitude of teams who own different parts of the sysroot (including us for the basic libc headers!). but if you have an issue with a camera header and an issue with a storage header and an issue with an input event header, well, those are going to have to go to completely different people on completely different teams. (so, in practice "file a separate [buganizer, not github!] bug for each one, and if it doesn't end up assigned to an appropriate adult, you can try letting us know and we can see if we can find the right person". tbh, if you use git log you can probably tell the person doing the triage who they should be talking to. they don't tend to have git log skills.)
I'd like to have (more) complete (non-)nullability annotations as well as thread safety/threading guarantees for both structures/pointers and callbacks (i.e. is an object internally synchronized? Can it be "moved" to another thread as long as it is not accessed concurrently? Will a callback be called on the current thread, or on one other thread? Or on multiple threads, possibly concurrently, hence requiring synchronization)? There was some activity and response initially, but as I started reporting more inconsistencies (with a general "please check the whole file as I cannot report every line"), activity died down.
going forward, there is a group of people who do look at every new api added to the ndk, and these are probably things that should go on their checklist. (meanwhile our team [specifically @ZijunZhaoCCK] has recently retconned nullability annotations for the entirety of libc, even if that wasn't the part of the sysroot you were actually talking about :-) )
@enh-google sure, I understand why this is the case, but wanted to report these issues as a whole and have a team of Googlers pick this up, rather than me painstakingly going through every API and requesting clarification everywhere, effectively picking up that job. Which I'm already doing to a significant extent, by using my free time to map NDK APIs into Rust, parsing the documentation, and finding various inconsistencies or general lack of clear and consistent documentation.
Sounds like I'll either have to leave it be, or file many separate issues on https://issuetracker.google.com/issues/new?component=192763&template=1032811 (assuming the NDK component is correct).
Notice that I'm trying to be helpful by pointing out lacking or inconsistent documentation, rather than figuring it out myself from the codebase and moving on with my day (with the added benefit of the semantics being locked in place). Asking a contributor to also take over part of someones job of triaging via git log, at that point I might as well end up on a payroll and submit documentation fixes upstream immediately (as already done once shown above).
without spawning a totally new issue for a simple question
Don't hesitate to use the "discussions" tab. That's what it's there for :)
where can I find what is scheduled to be included in the next (r26c) release?
Specifically in the context of sysroot updates, you don't. It's extremely rare that we update the sysroot in a minor release. When we do, because it comes in as a prebuilt, you won't see it happen until we do the update, at which point you'll see it in the CI builds. For this release in particular, it'd be a rather large amount of work to update the sysroot without causing problems (since the source I pull from now includes rv64 stuff, and we very much are not ready to put that in the NDK), so I don't expect any sysroot updates for any r26 minor releases.
More generally, "what's going to be in the next release?" is answered in the projects tab. There's no secret internal planning board; that board is the real one.
On that note I'm very much inclined to follow @DanAlbert's advice and migrate the ndk-sys crate to NDK CI builds because of all the missing API from the published NDK as pointed out above.
SGTM, but beware all the usual problems of living at HEAD. There will be non-final stuff in there. All the finalized APIs should be 100% stable (and if they aren't, that's a major bug and we'd want to fix it asap), and the non-final stuff probably isn't of interest to you anwyay.
Also notice that while this API takes an ADataSpace (should be enum ADataSpace to be valid C), all other APIs take an int dataSpace.
Which of the two is correct?
The enum. Older APIs use int (usually int32_t) because we used to support GCC, which didn't support specifying the backing type of an enum in C. We only support Clang now, which does allow that. We previously couldn't use enum directly in the ABI because without the specified backing type, we couldn't defend against the size/alignment of the enum changing. Now that we can, we prefer that for type safety (as well as improving self-documentation and IDE behavior).
We haven't retroactively updated all the older APIs (no bandwidth to do so, and in some cases it's actually not possible because the real API is union { the_enum, some_other_crap }), so you'll see a mix.
wanted to report these issues as a whole and have a team of Googlers pick this up
Sadly there's no team to do that. It's never really worked in my experience anyway. I could convert your mega-bug into a dozen better scoped bugs, but you'll need to be there for the follow up questions anyway. Plus, you, as a real person, are more likely to be listened to than I am.
(assuming the NDK component is correct).
It isn't. That's not even supposed to be open 😩
See the "documentation bug" listed on our "new issue" page:
Notice that I'm trying to be helpful by pointing out lacking or inconsistent documentation, rather than figuring it out myself from the codebase and moving on with my day
We do appreciate that, fwiw.
Asking a contributor to also take over part of someones job of triaging via git log, at that point I might as well end up on a payroll and submit documentation fixes upstream immediately (as already done once shown above).
Agreed that it sucks, but I assume you're rather us be honest about how much it sucks than pretend it doesn't.
More generally, "what's going to be in the next release?" is answered in the projects tab. There's no secret internal planning board; that board is the real one.
Unless I'm looking in the wrong place, https://github.com/orgs/android/projects/7/views/1 doesn't really have a clear "you'll get the new JNI functions for SurfaceControl and SurfaceTransaction, a binding for AImageReader_newWithDataSpace() from Android 14, etc".
SGTM, but beware all the usual problems of living at HEAD. There will be non-final stuff in there. All the finalized APIs should be 100% stable (and if they aren't, that's a major bug and we'd want to fix it asap), and the non-final stuff probably isn't of interest to you anwyay.
Tbh it's looking great, and I'll only use APIs that have a clear Available since XX (or APIs that were forgotten when someone ported it long ago). Not sure what to do with enum variants though, and if it makes sense to gate them.
See the changes for yourself: https://github.com/rust-mobile/ndk/commit/11f350dda0c56bebb46f6619220c06be89f2fe2c
The enum. Older APIs use
int(usuallyint32_t) because we used to support GCC, which didn't support specifying the backing type of an enum in C. We only support Clang now, which does allow that. We previously couldn't useenumdirectly in the ABI because without the specified backing type, we couldn't defend against the size/alignment of the enum changing. Now that we can, we prefer that for type safety (as well as improving self-documentation and IDE behavior).We haven't retroactively updated all the older APIs (no bandwidth to do so, and in some cases it's actually not possible because the real API is
union { the_enum, some_other_crap }), so you'll see a mix.
Good stuff. I might even submit some fixes for this upstream as it greatly helps our cause too.
Note that enum ADataSpace here doesn't actually have a storage specifier (https://cs.android.com/android/platform/superproject/main/+/main:frameworks/native/libs/nativewindow/include/android/data_space.h;l=40?q=adataspace) so I'm not sure if it can be used like that in the SurfaceControl APIs yet.
wanted to report these issues as a whole and have a team of Googlers pick this up
Sadly there's no team to do that. It's never really worked in my experience anyway. I could convert your mega-bug into a dozen better scoped bugs, but you'll need to be there for the follow up questions anyway. Plus, you, as a real person, are more likely to be listened to than I am.
Perhaps individual teams could pick this up on their own, rather than there being a high-level team coordinating fixes. However, having a high-level team coordinating consistent API and documentation (the "group of people" mentioned in https://github.com/android/ndk/issues/1920#issuecomment-1877911064) but I might be dreaming at this point.
Also, hello robot? I thought I was talking to a real Googler :grimacing:. Regardless, my experience as non-Googler (when it came to outsider AOSP contributions) wasn't too great.
(assuming the NDK component is correct).
It isn't. That's not even supposed to be open 😩
See the "documentation bug" listed on our "new issue" page:
The "NDK component" is referring to the issuetracker, your screenshot is from GitHub.
Following that link though, I'm supposed to end up in framework (that's where most of the headers come from anyway): https://issuetracker.google.com/issues?q=componentid:192705%2B
Please let me know if there are any of my open issues here that I should better migrate (I believe the answer will be "yes").
Can I update the existing reports to Framework too?
Notice that I'm trying to be helpful by pointing out lacking or inconsistent documentation, rather than figuring it out myself from the codebase and moving on with my day
We do appreciate that, fwiw.
It's not something I'd hope to keep doing forward, but I guess API-completeness and correctness (of the Rust crate, and the NDK C bindings as a result) just lies close to my heart.
Asking a contributor to also take over part of someones job of triaging via git log, at that point I might as well end up on a payroll and submit documentation fixes upstream immediately (as already done once shown above).
Agreed that it sucks, but I assume you're rather us be honest about how much it sucks than pretend it doesn't.
Fair enough. I'll file a few and see how it goes.
More generally, "what's going to be in the next release?" is answered in the projects tab. There's no secret internal planning board; that board is the real one.
Unless I'm looking in the wrong place, https://github.com/orgs/android/projects/7/views/1 doesn't really have a clear "you'll get the new JNI functions for SurfaceControl and SurfaceTransaction, a binding for AImageReader_newWithDataSpace() from Android 14, etc".
We don't know if there will be a sysroot update in r27 yet or not.
You're right though, I was leaning a bit too heavily on the phrase "generally". The changelog tells you when the sysroot gets updated, but there's rarely a tracking bug for it.
Good stuff. I might even submit some fixes for [int -> enum migration] upstream as it greatly helps our cause too.
And the good news there is that I'm one of the reviewers you'll need for that anyway. Like I said there are a couple very hairy cases, but I expect most of them are straightforward.
Note that enum ADataSpace here doesn't actually have a storage specifier (https://cs.android.com/android/platform/superproject/main/+/main:frameworks/native/libs/nativewindow/include/android/data_space.h;l=40?q=adataspace) so I'm not sure if it can be used like that in the SurfaceControl APIs yet.
😱
Okay, that's something we missed in review. https://android-review.googlesource.com/c/platform/frameworks/native/+/2902242.
Also, hello robot? I thought I was talking to a real Googler 😬. Regardless, my experience as non-Googler (when it came to outsider AOSP contributions) wasn't too great.
"Real person" as in "an actual user" :)
I'll have better luck finding someone if triage fails, but problems reported by an actual user should always be more interesting than whatever I think :)
The "NDK component" is referring to the issuetracker, your screenshot is from GitHub.
Yeah, there isn't supposed to be an open NDK component in issuetracker. That's /dev/null 😞 There shouldn't be anything pointing you there though. b.android.com shouldn't mention it (and I don't think it does?), and neither does our github page. It should only be discoverable by searching within issuetracker, but I wouldn't recommend doing that. Different teams have different triage processes and if you file in an arbitrary component it may never been seen by anyone. Always follow b.android.com unless someone tells you otherwise. (Yes, I can hear how stupid that is as I type it, but that is how it works)
No worries, I'll keep an eye out for sysroot updates but will open a Rust crate PR soon that migrates to the CI builds, they're exactly what I need :ok_hand:
Good stuff. I might even submit some fixes for [int -> enum migration] upstream as it greatly helps our cause too.
And the good news there is that I'm one of the reviewers you'll need for that anyway. Like I said there are a couple very hairy cases, but I expect most of them are straightforward.
I don't think I'll get to that any time soon, unfortunately. It'd massively help me with the ndk crate, but I'm out all of February and, unlike your MR that got reviewed the same day, the one I've uploaded at https://android-review.googlesource.com/c/platform/frameworks/native/+/2897863 remains untouched for 2 weeks :-1:. Being a non-Googler has this as a massive disadvantage :disappointed:
Can you help assign that one to the right people and push it through, please?
[missing ADataSpace storage specifier]
😱
Okay, that's something we missed in review. https://android-review.googlesource.com/c/platform/frameworks/native/+/2902242.
Thanks! I've linked this at https://github.com/rust-mobile/ndk/pull/459#discussion_r1457503228 to confirm that our type changes in Rust make sense (and hope to remove the casts once this lands in the sysroot).
Also, hello robot? I thought I was talking to a real Googler 😬. Regardless, my experience as non-Googler (when it came to outsider AOSP contributions) wasn't too great.
"Real person" as in "an actual user" :)
As above, for https://android-review.googlesource.com/c/platform/frameworks/native/+/2897863, they don't expect "actual users" to also be "actual developers" that are capable of contributing changes to AOSP.
the one I've uploaded at https://android-review.googlesource.com/c/platform/frameworks/native/+/2897863 remains untouched for 2 weeks 👎
You've added no reviewer. Doubtful anyone was notified (subscribing to all new changes in frameworks/base would probably generate thousands of emails a day, so even if anyone is doing that, there's no way they'd have seen it). There's an "add owners" or "suggest owners" button on the page you need to click to add a reviewer:
I've gone ahead and done that.
Thanks, I wouldn't have expected there to be even more manual action. The system should really be based on code owners.
Is this documented somewhere? At least this is what I expected Gerrit to do: https://source.android.com/docs/setup/contribute/life-of-a-patch
The system should really be based on code owners.
It is, but it doesn't auto-add reviewers. You would not believe the amount of spam we get.
Is this documented somewhere?
Sure, the flowchart goes two-ways and I had hoped Gerrit would pick up codeowners (without really paying attention to explicitly-assigned reviewers), and pinging you as reviewer here would have implicitly held for the left branch :)
Oh, indeed it does. That's... misleading.
And yes. When in doubt, bothering whatever droid you happen to know usually works.
https://source.android.com/docs/setup/contribute/submit-patches#request-review is more explicit, fwiw. That's the "full instructions" link at the top of the flow chart.
Thanks :)
When submitting new patches, would I just select all of the codeowners?
I find it's better to pick one at first. If a CL has ten reviewers assigned, everyone thinks someone else will do it, and so no one thinks it's their job. I usually start with one, then add more if it doesn't get any attention (yes, Googlers have this problem too).
I find it's better to pick one at first. If a CL has ten reviewers assigned, everyone thinks someone else will do it, and so no one thinks it's their job. I usually start with one, then add more if it doesn't get any attention (yes, Googlers have this problem too).
(yep, another googler here, saying "me too" to both this problem and this tactic.)
Sounds good, thanks for thinking with me :)
Have submitted a bunch of new CLs with additional type improvements, let's hope we can push these through...
