1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.documentsui.inspector; 17 18 import android.content.Context; 19 import android.content.res.Resources; 20 import android.os.AsyncTask; 21 import android.os.Bundle; 22 import android.provider.DocumentsContract; 23 import android.util.AttributeSet; 24 import android.widget.TextView; 25 26 import androidx.annotation.StringRes; 27 28 import com.android.documentsui.R; 29 import com.android.documentsui.base.DocumentInfo; 30 import com.android.documentsui.base.DummyLookup; 31 import com.android.documentsui.base.Lookup; 32 import com.android.documentsui.inspector.InspectorController.DebugDisplay; 33 34 import java.text.NumberFormat; 35 import java.util.ArrayList; 36 import java.util.Arrays; 37 import java.util.Collections; 38 import java.util.List; 39 import java.util.concurrent.Executor; 40 41 /** 42 * Organizes and Displays the debug information about a file. This view 43 * should only be made visible when build is debuggable and system policies 44 * allow debug "stuff". 45 */ 46 public class DebugView extends TableView implements DebugDisplay { 47 48 private final Context mContext; 49 private final Resources mRes; 50 private Lookup<String, Executor> mExecutors = new DummyLookup<>(); 51 DebugView(Context context)52 public DebugView(Context context) { 53 this(context, null); 54 } 55 DebugView(Context context, AttributeSet attrs)56 public DebugView(Context context, AttributeSet attrs) { 57 this(context, attrs, 0); 58 } 59 DebugView(Context context, AttributeSet attrs, int defStyleAttr)60 public DebugView(Context context, AttributeSet attrs, int defStyleAttr) { 61 super(context, attrs, defStyleAttr); 62 mContext = context; 63 mRes = context.getResources(); 64 } 65 init(Lookup<String, Executor> executors)66 void init(Lookup<String, Executor> executors) { 67 assert executors != null; 68 mExecutors = executors; 69 } 70 71 @Override accept(DocumentInfo info)72 public void accept(DocumentInfo info) { 73 setTitle(R.string.inspector_debug_section, true); 74 75 put(R.string.debug_content_uri, info.derivedUri.toString()); 76 put(R.string.debug_document_id, info.documentId); 77 put(R.string.debug_raw_mimetype, info.mimeType); 78 put(R.string.debug_stream_types, "-"); 79 put(R.string.debug_raw_size, NumberFormat.getInstance().format(info.size)); 80 put(R.string.debug_is_archive, info.isArchive()); 81 put(R.string.debug_is_container, info.isContainer()); 82 put(R.string.debug_is_partial, info.isPartial()); 83 put(R.string.debug_is_virtual, info.isVirtual()); 84 put(R.string.debug_supports_create, info.isCreateSupported()); 85 put(R.string.debug_supports_delete, info.isDeleteSupported()); 86 put(R.string.debug_supports_metadata, info.isMetadataSupported()); 87 put(R.string.debug_supports_move, info.isMoveSupported()); 88 put(R.string.debug_supports_remove, info.isRemoveSupported()); 89 put(R.string.debug_supports_rename, info.isRenameSupported()); 90 put(R.string.debug_supports_settings, info.isSettingsSupported()); 91 put(R.string.debug_supports_thumbnail, info.isThumbnailSupported()); 92 put(R.string.debug_supports_weblink, info.isWeblinkSupported()); 93 put(R.string.debug_supports_write, info.isWriteSupported()); 94 95 // Load Document stream types of the file. For virtual files, this should be 96 // something other than the primary type of the file. 97 Executor executor = mExecutors.lookup(info.derivedUri.getAuthority()); 98 if (executor != null) { 99 new AsyncTask<Void, Void, String[]>() { 100 @Override 101 protected String[] doInBackground(Void... params) { 102 return mContext.getContentResolver().getStreamTypes(info.derivedUri, "*/*"); 103 } 104 105 @Override 106 protected void onPostExecute(String[] streamTypes) { 107 put(R.string.debug_stream_types, 108 streamTypes != null ? Arrays.toString(streamTypes) : "[]"); 109 } 110 }.executeOnExecutor(executor, (Void[]) null); 111 } 112 } 113 114 @Override accept(Bundle metadata)115 public void accept(Bundle metadata) { 116 if (metadata == null) { 117 return; 118 } 119 120 String[] types = metadata.getStringArray(DocumentsContract.METADATA_TYPES); 121 if (types == null) { 122 return; 123 } 124 125 for (String type : types) { 126 dumpMetadata(type, metadata.getBundle(type)); 127 } 128 } 129 dumpMetadata(String type, Bundle bundle)130 private void dumpMetadata(String type, Bundle bundle) { 131 String title = mContext.getResources().getString( 132 R.string.inspector_debug_metadata_section); 133 putTitle(String.format(title, type), true); 134 List<String> keys = new ArrayList<>(bundle.keySet()); 135 Collections.sort(keys); 136 for (String key : keys) { 137 put(key, String.valueOf(bundle.get(key))); 138 } 139 } 140 put(@tringRes int key, boolean value)141 private void put(@StringRes int key, boolean value) { 142 KeyValueRow row = put(mRes.getString(key), String.valueOf(value)); 143 TextView valueView = ((TextView) row.findViewById(R.id.table_row_value)); 144 valueView.setTextColor(value ? 0xFF006400 : 0xFF9A2020); 145 } 146 } 147