Every consumer that has to decide "should I offer myself for this file?" before opening it ends up rebuilding a format table that the core already almost has. OpenDocument.droid now carries three copies of one, and keeps them honest with an instrumented test — that work belongs here.
What the core exposes today (6.0.1)
file_type_by_file_extension(ext) — extension → FileType
file_type_by_mimetype(mime) — mime → FileType
mimetype_by_file_type(type) — FileType → one mime, or throw UnsupportedFileType
file_category_by_file_type, document_type_by_file_type
list_file_types(path) / mimetype(path) — but those need the bytes
Why that is not enough
1. The mappings are not surjective, and only sometimes carry aliases.
file_type_by_file_extension handles odt/fodt/ott/odm for one type, and six spellings of jpeg — so aliases are clearly an intended pattern. But ooxml gets only docx/pptx/xlsx and the legacy formats only doc/ppt/xls. Verified on device against 6.0.1, every one of these is FileType::unknown:
docm dotx dotm dot xlsm xltx xltm xlt xlsb pptm potx potm pot ppsx ppsm pps
They are the same packages as the x suffixed ones and the core renders them fine once libmagic has seen the bytes — it is only the name-based lookup that does not know them.
file_type_by_mimetype is the same story: aliases for application/x-zip-compressed and for the font types, none for office. It does not know the ooxml template/slideshow/macro-enabled mime types, nor application/x-vnd.oasis.opendocument.*, which content providers on android hand out routinely.
2. mimetype_by_file_type is one-to-one, so it cannot be enumerated into a filter.
A caller that wants "all mime types you would accept" cannot get there: the reverse direction gives one canonical spelling per type and throws for word_perfect, rich_text_format, compound_file_binary_format, starview_metafile and office_open_xml_encrypted.
3. There is no "can you render this?" question.
Nothing says which FileTypes have an HTML translation. Consumers hardcode it. OpenDocument.droid currently claims odf + ooxml + legacy MS + pdf, worked out by looking at which formats have reference output in this repo — which silently went stale: the app shipped a // TODO: enable pptx too long after the core could do pptx, and let .doc through only by accident.
4. There is no "can you edit/save this?" question that does not require opening the file.
Document::is_editable() / is_savable() are the right answers and we now use them — but only after a full parse. Deciding whether to offer an edit affordance earlier means guessing, which is what we used to do by mime prefix and got wrong for the legacy formats the moment they started reaching the core.
What it costs downstream
In OpenDocument.droid, one logical set is spelled three times:
SupportedDocumentTypes — mime prefixes for what the core renders, mime prefixes for what its own raw loader shows, plus an extension fallback for the application/octet-stream providers volunteer when they know nothing better
- the
STRICT_CATCH intent-filter in AndroidManifest.xml — 29 extensions × 7 path patterns × 2 filters, plus every mime spelling written out, because an intent-filter matches a mime type exactly
- previously a third copy inside the app's
CoreLoader, now removed
The manifest cannot read a kotlin list, so we added an instrumented SupportedFormatsTest that walks FileType.values(), asks mimetypeByFileType for each, and asserts the app's table and the android package manager give the same answer — plus separate cases for the ooxml variants, since the FileType walk provably cannot reach spellings the core never produces. That test exists purely because the core cannot be asked directly.
What would help
Roughly in order of usefulness to us:
mimetypes_by_file_type(FileType) -> vector<string_view> and file_extensions_by_file_type(FileType) -> vector<string_view> — all spellings, canonical first. That alone lets a consumer generate its own filter table instead of hand-maintaining one.
- Teach both lookups the missing aliases — the ooxml templates/slideshows/macro-enabled extensions and mime types, and
application/x-vnd.oasis.opendocument.*. Cheap, and independently useful.
bool is_html_translatable(FileType) (or a list_translatable_file_types()), so "what can you render" stops being folklore derived from the reference-output directory.
- Editability by
FileType, if it is knowable without a parse — even a conservative "never editable" for the formats that categorically are not (the legacy binaries, ooxml spreadsheets/presentations) would let a UI decide before opening. If it genuinely depends on the document, saying so in the docs is enough.
- All of the above reachable from the JNI bindings, since that is where we consume it.
Happy to help with any of these, and to delete the app-side table once there is something to replace it with.
Every consumer that has to decide "should I offer myself for this file?" before opening it ends up rebuilding a format table that the core already almost has. OpenDocument.droid now carries three copies of one, and keeps them honest with an instrumented test — that work belongs here.
What the core exposes today (6.0.1)
file_type_by_file_extension(ext)— extension →FileTypefile_type_by_mimetype(mime)— mime →FileTypemimetype_by_file_type(type)—FileType→ one mime, orthrow UnsupportedFileTypefile_category_by_file_type,document_type_by_file_typelist_file_types(path)/mimetype(path)— but those need the bytesWhy that is not enough
1. The mappings are not surjective, and only sometimes carry aliases.
file_type_by_file_extensionhandlesodt/fodt/ott/odmfor one type, and six spellings of jpeg — so aliases are clearly an intended pattern. But ooxml gets onlydocx/pptx/xlsxand the legacy formats onlydoc/ppt/xls. Verified on device against 6.0.1, every one of these isFileType::unknown:They are the same packages as the
xsuffixed ones and the core renders them fine once libmagic has seen the bytes — it is only the name-based lookup that does not know them.file_type_by_mimetypeis the same story: aliases forapplication/x-zip-compressedand for the font types, none for office. It does not know the ooxml template/slideshow/macro-enabled mime types, norapplication/x-vnd.oasis.opendocument.*, which content providers on android hand out routinely.2.
mimetype_by_file_typeis one-to-one, so it cannot be enumerated into a filter.A caller that wants "all mime types you would accept" cannot get there: the reverse direction gives one canonical spelling per type and throws for
word_perfect,rich_text_format,compound_file_binary_format,starview_metafileandoffice_open_xml_encrypted.3. There is no "can you render this?" question.
Nothing says which
FileTypes have an HTML translation. Consumers hardcode it. OpenDocument.droid currently claims odf + ooxml + legacy MS + pdf, worked out by looking at which formats have reference output in this repo — which silently went stale: the app shipped a// TODO: enable pptx toolong after the core could do pptx, and let.docthrough only by accident.4. There is no "can you edit/save this?" question that does not require opening the file.
Document::is_editable()/is_savable()are the right answers and we now use them — but only after a full parse. Deciding whether to offer an edit affordance earlier means guessing, which is what we used to do by mime prefix and got wrong for the legacy formats the moment they started reaching the core.What it costs downstream
In OpenDocument.droid, one logical set is spelled three times:
SupportedDocumentTypes— mime prefixes for what the core renders, mime prefixes for what its own raw loader shows, plus an extension fallback for theapplication/octet-streamproviders volunteer when they know nothing betterSTRICT_CATCHintent-filterinAndroidManifest.xml— 29 extensions × 7 path patterns × 2 filters, plus every mime spelling written out, because an intent-filter matches a mime type exactlyCoreLoader, now removedThe manifest cannot read a kotlin list, so we added an instrumented
SupportedFormatsTestthat walksFileType.values(), asksmimetypeByFileTypefor each, and asserts the app's table and the android package manager give the same answer — plus separate cases for the ooxml variants, since theFileTypewalk provably cannot reach spellings the core never produces. That test exists purely because the core cannot be asked directly.What would help
Roughly in order of usefulness to us:
mimetypes_by_file_type(FileType) -> vector<string_view>andfile_extensions_by_file_type(FileType) -> vector<string_view>— all spellings, canonical first. That alone lets a consumer generate its own filter table instead of hand-maintaining one.application/x-vnd.oasis.opendocument.*. Cheap, and independently useful.bool is_html_translatable(FileType)(or alist_translatable_file_types()), so "what can you render" stops being folklore derived from the reference-output directory.FileType, if it is knowable without a parse — even a conservative "never editable" for the formats that categorically are not (the legacy binaries, ooxml spreadsheets/presentations) would let a UI decide before opening. If it genuinely depends on the document, saying so in the docs is enough.Happy to help with any of these, and to delete the app-side table once there is something to replace it with.