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.annotation.StringRes; 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.os.AsyncTask; 22 import android.os.Bundle; 23 import android.provider.DocumentsContract; 24 import android.util.AttributeSet; 25 import android.widget.TextView; 26 27 import com.android.documentsui.R; 28 import com.android.documentsui.base.DocumentInfo; 29 import com.android.documentsui.base.DummyLookup; 30 import com.android.documentsui.base.Lookup; 31 import com.android.documentsui.inspector.InspectorController.DebugDisplay; 32 33 import java.text.NumberFormat; 34 import java.util.ArrayList; 35 import java.util.Arrays; 36 import java.util.Collections; 37 import java.util.List; 38 import java.util.concurrent.Executor; 39 40 /** 41 * Organizes and Displays the debug information about a file. This view 42 * should only be made visible when build is debuggable and system policies 43 * allow debug "stuff". 44 */ 45 public class DebugView extends TableView implements DebugDisplay { 46 47 private final Context mContext; 48 private final Resources mRes; 49 private Lookup<String, Executor> mExecutors = new DummyLookup<>(); 50 DebugView(Context context)51 public DebugView(Context context) { 52 this(context, null); 53 } 54 DebugView(Context context, AttributeSet attrs)55 public DebugView(Context context, AttributeSet attrs) { 56 this(context, attrs, 0); 57 } 58 DebugView(Context context, AttributeSet attrs, int defStyleAttr)59 public DebugView(Context context, AttributeSet attrs, int defStyleAttr) { 60 super(context, attrs, defStyleAttr); 61 mContext = context; 62 mRes = context.getResources(); 63 } 64 init(Lookup<String, Executor> executors)65 void init(Lookup<String, Executor> executors) { 66 assert executors != null; 67 setBackgroundColor(0xFFFFFFFF); // it's just debug. We do what we want! 68 mExecutors = executors; 69 } 70 71 @Override accept(DocumentInfo info)72 public void accept(DocumentInfo info) { 73 setTitle(R.string.inspector_debug_section, false); 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_remove, info.isRemoveSupported()); 88 put(R.string.debug_supports_rename, info.isRenameSupported()); 89 put(R.string.debug_supports_settings, info.isSettingsSupported()); 90 put(R.string.debug_supports_thumbnail, info.isThumbnailSupported()); 91 put(R.string.debug_supports_weblink, info.isWeblinkSupported()); 92 put(R.string.debug_supports_write, info.isWriteSupported()); 93 94 // Load Document stream types of the file. For virtual files, this should be 95 // something other than the primary type of the file. 96 Executor executor = mExecutors.lookup(info.derivedUri.getAuthority()); 97 if (executor != null) { 98 new AsyncTask<Void, Void, String[]>() { 99 @Override 100 protected String[] doInBackground(Void... params) { 101 return mContext.getContentResolver().getStreamTypes(info.derivedUri, "*/*"); 102 } 103 104 @Override 105 protected void onPostExecute(String[] streamTypes) { 106 put(R.string.debug_stream_types, 107 streamTypes != null ? Arrays.toString(streamTypes) : "[]"); 108 } 109 }.executeOnExecutor(executor, (Void[]) null); 110 } 111 } 112 113 @Override accept(Bundle metadata)114 public void accept(Bundle metadata) { 115 if (metadata == null) { 116 return; 117 } 118 119 String[] types = metadata.getStringArray(DocumentsContract.METADATA_TYPES); 120 if (types == null) { 121 return; 122 } 123 124 for (String type : types) { 125 dumpMetadata(type, metadata.getBundle(type)); 126 } 127 } 128 dumpMetadata(String type, Bundle bundle)129 private void dumpMetadata(String type, Bundle bundle) { 130 String title = mContext.getResources().getString( 131 R.string.inspector_debug_metadata_section); 132 putTitle(String.format(title, type), true); 133 List<String> keys = new ArrayList<>(bundle.keySet()); 134 Collections.sort(keys); 135 for (String key : keys) { 136 put(key, String.valueOf(bundle.get(key))); 137 } 138 } 139 put(@tringRes int key, boolean value)140 private void put(@StringRes int key, boolean value) { 141 KeyValueRow row = put(mRes.getString(key), String.valueOf(value)); 142 TextView valueView = ((TextView) row.findViewById(R.id.table_row_value)); 143 valueView.setTextColor(value ? 0xFF006400 : 0xFF9A2020); 144 } 145 } 146