/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.util; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentResolver.MimeTypeInfo; import android.content.res.Resources; import android.graphics.drawable.Icon; import android.text.TextUtils; import android.util.ArrayMap; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import libcore.content.type.MimeMap; import java.util.Locale; import java.util.Objects; public class MimeIconUtils { @GuardedBy("sCache") private static final ArrayMap sCache = new ArrayMap<>(); private static MimeTypeInfo buildTypeInfo(String mimeType, int iconId, int labelId, int extLabelId) { final Resources res = Resources.getSystem(); // If this MIME type has an extension, customize the label final CharSequence label; final String ext = MimeMap.getDefault().guessExtensionFromMimeType(mimeType); if (!TextUtils.isEmpty(ext) && extLabelId != -1) { label = res.getString(extLabelId, ext.toUpperCase(Locale.US)); } else { label = res.getString(labelId); } return new MimeTypeInfo(Icon.createWithResource(res, iconId), label, label); } private static @Nullable MimeTypeInfo buildTypeInfo(@NonNull String mimeType) { switch (mimeType) { case "inode/directory": case "vnd.android.document/directory": return buildTypeInfo(mimeType, R.drawable.ic_doc_folder, R.string.mime_type_folder, -1); case "application/vnd.android.package-archive": return buildTypeInfo(mimeType, R.drawable.ic_doc_apk, R.string.mime_type_apk, -1); case "application/pgp-keys": case "application/pgp-signature": case "application/x-pkcs12": case "application/x-pkcs7-certreqresp": case "application/x-pkcs7-crl": case "application/x-x509-ca-cert": case "application/x-x509-user-cert": case "application/x-pkcs7-certificates": case "application/x-pkcs7-mime": case "application/x-pkcs7-signature": return buildTypeInfo(mimeType, R.drawable.ic_doc_certificate, R.string.mime_type_generic, R.string.mime_type_generic_ext); case "application/rdf+xml": case "application/rss+xml": case "application/x-object": case "application/xhtml+xml": case "text/css": case "text/html": case "text/xml": case "text/x-c++hdr": case "text/x-c++src": case "text/x-chdr": case "text/x-csrc": case "text/x-dsrc": case "text/x-csh": case "text/x-haskell": case "text/x-java": case "text/x-literate-haskell": case "text/x-pascal": case "text/x-tcl": case "text/x-tex": case "application/x-latex": case "application/x-texinfo": case "application/atom+xml": case "application/ecmascript": case "application/json": case "application/javascript": case "application/xml": case "text/javascript": case "application/x-javascript": return buildTypeInfo(mimeType, R.drawable.ic_doc_codes, R.string.mime_type_document, R.string.mime_type_document_ext); case "application/mac-binhex40": case "application/rar": case "application/zip": case "application/x-apple-diskimage": case "application/x-debian-package": case "application/x-gtar": case "application/x-iso9660-image": case "application/x-lha": case "application/x-lzh": case "application/x-lzx": case "application/x-stuffit": case "application/x-tar": case "application/x-webarchive": case "application/x-webarchive-xml": case "application/gzip": case "application/x-7z-compressed": case "application/x-deb": case "application/x-rar-compressed": return buildTypeInfo(mimeType, R.drawable.ic_doc_compressed, R.string.mime_type_compressed, R.string.mime_type_compressed_ext); case "text/x-vcard": case "text/vcard": return buildTypeInfo(mimeType, R.drawable.ic_doc_contact, R.string.mime_type_generic, R.string.mime_type_generic_ext); case "text/calendar": case "text/x-vcalendar": return buildTypeInfo(mimeType, R.drawable.ic_doc_event, R.string.mime_type_generic, R.string.mime_type_generic_ext); case "application/x-font": case "application/font-woff": case "application/x-font-woff": case "application/x-font-ttf": return buildTypeInfo(mimeType, R.drawable.ic_doc_font, R.string.mime_type_generic, R.string.mime_type_generic_ext); case "application/vnd.oasis.opendocument.graphics": case "application/vnd.oasis.opendocument.graphics-template": case "application/vnd.oasis.opendocument.image": case "application/vnd.stardivision.draw": case "application/vnd.sun.xml.draw": case "application/vnd.sun.xml.draw.template": case "application/vnd.google-apps.drawing": return buildTypeInfo(mimeType, R.drawable.ic_doc_image, R.string.mime_type_image, R.string.mime_type_image_ext); case "application/pdf": return buildTypeInfo(mimeType, R.drawable.ic_doc_pdf, R.string.mime_type_document, R.string.mime_type_document_ext); case "application/vnd.stardivision.impress": case "application/vnd.sun.xml.impress": case "application/vnd.sun.xml.impress.template": case "application/x-kpresenter": case "application/vnd.oasis.opendocument.presentation": case "application/vnd.google-apps.presentation": return buildTypeInfo(mimeType, R.drawable.ic_doc_presentation, R.string.mime_type_presentation, R.string.mime_type_presentation_ext); case "application/vnd.oasis.opendocument.spreadsheet": case "application/vnd.oasis.opendocument.spreadsheet-template": case "application/vnd.stardivision.calc": case "application/vnd.sun.xml.calc": case "application/vnd.sun.xml.calc.template": case "application/x-kspread": case "application/vnd.google-apps.spreadsheet": return buildTypeInfo(mimeType, R.drawable.ic_doc_spreadsheet, R.string.mime_type_spreadsheet, R.string.mime_type_spreadsheet_ext); case "application/vnd.oasis.opendocument.text": case "application/vnd.oasis.opendocument.text-master": case "application/vnd.oasis.opendocument.text-template": case "application/vnd.oasis.opendocument.text-web": case "application/vnd.stardivision.writer": case "application/vnd.stardivision.writer-global": case "application/vnd.sun.xml.writer": case "application/vnd.sun.xml.writer.global": case "application/vnd.sun.xml.writer.template": case "application/x-abiword": case "application/x-kword": case "application/vnd.google-apps.document": return buildTypeInfo(mimeType, R.drawable.ic_doc_document, R.string.mime_type_document, R.string.mime_type_document_ext); case "application/x-quicktimeplayer": case "application/x-shockwave-flash": return buildTypeInfo(mimeType, R.drawable.ic_doc_video, R.string.mime_type_video, R.string.mime_type_video_ext); case "application/msword": case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": case "application/vnd.openxmlformats-officedocument.wordprocessingml.template": return buildTypeInfo(mimeType, R.drawable.ic_doc_word, R.string.mime_type_document, R.string.mime_type_document_ext); case "application/vnd.ms-excel": case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": case "application/vnd.openxmlformats-officedocument.spreadsheetml.template": return buildTypeInfo(mimeType, R.drawable.ic_doc_excel, R.string.mime_type_spreadsheet, R.string.mime_type_spreadsheet_ext); case "application/vnd.ms-powerpoint": case "application/vnd.openxmlformats-officedocument.presentationml.presentation": case "application/vnd.openxmlformats-officedocument.presentationml.template": case "application/vnd.openxmlformats-officedocument.presentationml.slideshow": return buildTypeInfo(mimeType, R.drawable.ic_doc_powerpoint, R.string.mime_type_presentation, R.string.mime_type_presentation_ext); default: return buildGenericTypeInfo(mimeType); } } private static @Nullable MimeTypeInfo buildGenericTypeInfo(@NonNull String mimeType) { // Look for partial matches if (mimeType.startsWith("audio/")) { return buildTypeInfo(mimeType, R.drawable.ic_doc_audio, R.string.mime_type_audio, R.string.mime_type_audio_ext); } else if (mimeType.startsWith("video/")) { return buildTypeInfo(mimeType, R.drawable.ic_doc_video, R.string.mime_type_video, R.string.mime_type_video_ext); } else if (mimeType.startsWith("image/")) { return buildTypeInfo(mimeType, R.drawable.ic_doc_image, R.string.mime_type_image, R.string.mime_type_image_ext); } else if (mimeType.startsWith("text/")) { return buildTypeInfo(mimeType, R.drawable.ic_doc_text, R.string.mime_type_document, R.string.mime_type_document_ext); } // As one last-ditch effort, try "bouncing" the MIME type through its // default extension. This handles cases like "application/x-flac" to // ".flac" to "audio/flac". MimeMap mimeMap = MimeMap.getDefault(); final String bouncedMimeType = mimeMap .guessMimeTypeFromExtension(mimeMap.guessExtensionFromMimeType(mimeType)); if (bouncedMimeType != null && !Objects.equals(mimeType, bouncedMimeType)) { return buildTypeInfo(bouncedMimeType); } // Worst case, return a generic file return buildTypeInfo(mimeType, R.drawable.ic_doc_generic, R.string.mime_type_generic, R.string.mime_type_generic_ext); } public static @NonNull MimeTypeInfo getTypeInfo(@NonNull String mimeType) { // Normalize MIME type mimeType = mimeType.toLowerCase(Locale.US); synchronized (sCache) { MimeTypeInfo res = sCache.get(mimeType); if (res == null) { res = buildTypeInfo(mimeType); sCache.put(mimeType, res); } return res; } } }