1 /* 2 * Copyright (C) 2013 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 17 package com.android.documentsui.model; 18 19 import static com.android.documentsui.model.DocumentInfo.getCursorInt; 20 import static com.android.documentsui.model.DocumentInfo.getCursorLong; 21 import static com.android.documentsui.model.DocumentInfo.getCursorString; 22 23 import android.content.Context; 24 import android.database.Cursor; 25 import android.graphics.drawable.Drawable; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.provider.DocumentsContract.Root; 29 import android.text.TextUtils; 30 31 import com.android.documentsui.IconUtils; 32 import com.android.documentsui.R; 33 34 import java.io.DataInputStream; 35 import java.io.DataOutputStream; 36 import java.io.IOException; 37 import java.net.ProtocolException; 38 import java.util.Objects; 39 40 /** 41 * Representation of a {@link Root}. 42 */ 43 public class RootInfo implements Durable, Parcelable { 44 private static final int VERSION_INIT = 1; 45 private static final int VERSION_DROP_TYPE = 2; 46 47 public String authority; 48 public String rootId; 49 public int flags; 50 public int icon; 51 public String title; 52 public String summary; 53 public String documentId; 54 public long availableBytes; 55 public String mimeTypes; 56 57 /** Derived fields that aren't persisted */ 58 public String derivedPackageName; 59 public String[] derivedMimeTypes; 60 public int derivedIcon; 61 62 public RootInfo() { 63 reset(); 64 } 65 66 @Override 67 public void reset() { 68 authority = null; 69 rootId = null; 70 flags = 0; 71 icon = 0; 72 title = null; 73 summary = null; 74 documentId = null; 75 availableBytes = -1; 76 mimeTypes = null; 77 78 derivedPackageName = null; 79 derivedMimeTypes = null; 80 derivedIcon = 0; 81 } 82 83 @Override 84 public void read(DataInputStream in) throws IOException { 85 final int version = in.readInt(); 86 switch (version) { 87 case VERSION_DROP_TYPE: 88 authority = DurableUtils.readNullableString(in); 89 rootId = DurableUtils.readNullableString(in); 90 flags = in.readInt(); 91 icon = in.readInt(); 92 title = DurableUtils.readNullableString(in); 93 summary = DurableUtils.readNullableString(in); 94 documentId = DurableUtils.readNullableString(in); 95 availableBytes = in.readLong(); 96 mimeTypes = DurableUtils.readNullableString(in); 97 deriveFields(); 98 break; 99 default: 100 throw new ProtocolException("Unknown version " + version); 101 } 102 } 103 104 @Override 105 public void write(DataOutputStream out) throws IOException { 106 out.writeInt(VERSION_DROP_TYPE); 107 DurableUtils.writeNullableString(out, authority); 108 DurableUtils.writeNullableString(out, rootId); 109 out.writeInt(flags); 110 out.writeInt(icon); 111 DurableUtils.writeNullableString(out, title); 112 DurableUtils.writeNullableString(out, summary); 113 DurableUtils.writeNullableString(out, documentId); 114 out.writeLong(availableBytes); 115 DurableUtils.writeNullableString(out, mimeTypes); 116 } 117 118 @Override 119 public int describeContents() { 120 return 0; 121 } 122 123 @Override 124 public void writeToParcel(Parcel dest, int flags) { 125 DurableUtils.writeToParcel(dest, this); 126 } 127 128 public static final Creator<RootInfo> CREATOR = new Creator<RootInfo>() { 129 @Override 130 public RootInfo createFromParcel(Parcel in) { 131 final RootInfo root = new RootInfo(); 132 DurableUtils.readFromParcel(in, root); 133 return root; 134 } 135 136 @Override 137 public RootInfo[] newArray(int size) { 138 return new RootInfo[size]; 139 } 140 }; 141 142 public static RootInfo fromRootsCursor(String authority, Cursor cursor) { 143 final RootInfo root = new RootInfo(); 144 root.authority = authority; 145 root.rootId = getCursorString(cursor, Root.COLUMN_ROOT_ID); 146 root.flags = getCursorInt(cursor, Root.COLUMN_FLAGS); 147 root.icon = getCursorInt(cursor, Root.COLUMN_ICON); 148 root.title = getCursorString(cursor, Root.COLUMN_TITLE); 149 root.summary = getCursorString(cursor, Root.COLUMN_SUMMARY); 150 root.documentId = getCursorString(cursor, Root.COLUMN_DOCUMENT_ID); 151 root.availableBytes = getCursorLong(cursor, Root.COLUMN_AVAILABLE_BYTES); 152 root.mimeTypes = getCursorString(cursor, Root.COLUMN_MIME_TYPES); 153 root.deriveFields(); 154 return root; 155 } 156 157 private void deriveFields() { 158 derivedMimeTypes = (mimeTypes != null) ? mimeTypes.split("\n") : null; 159 160 // TODO: remove these special case icons 161 if (isExternalStorage()) { 162 derivedIcon = R.drawable.ic_root_sdcard; 163 } else if (isDownloads()) { 164 derivedIcon = R.drawable.ic_root_download; 165 } else if (isImages()) { 166 derivedIcon = R.drawable.ic_doc_image; 167 } else if (isVideos()) { 168 derivedIcon = R.drawable.ic_doc_video; 169 } else if (isAudio()) { 170 derivedIcon = R.drawable.ic_doc_audio; 171 } 172 } 173 174 public boolean isRecents() { 175 return authority == null && rootId == null; 176 } 177 178 public boolean isExternalStorage() { 179 return "com.android.externalstorage.documents".equals(authority); 180 } 181 182 public boolean isDownloads() { 183 return "com.android.providers.downloads.documents".equals(authority); 184 } 185 186 public boolean isImages() { 187 return "com.android.providers.media.documents".equals(authority) 188 && "images_root".equals(rootId); 189 } 190 191 public boolean isVideos() { 192 return "com.android.providers.media.documents".equals(authority) 193 && "videos_root".equals(rootId); 194 } 195 196 public boolean isAudio() { 197 return "com.android.providers.media.documents".equals(authority) 198 && "audio_root".equals(rootId); 199 } 200 201 @Override 202 public String toString() { 203 return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}"; 204 } 205 206 public Drawable loadIcon(Context context) { 207 if (derivedIcon != 0) { 208 return context.getResources().getDrawable(derivedIcon); 209 } else { 210 return IconUtils.loadPackageIcon(context, authority, icon); 211 } 212 } 213 214 @Override 215 public boolean equals(Object o) { 216 if (o instanceof RootInfo) { 217 final RootInfo root = (RootInfo) o; 218 return Objects.equals(authority, root.authority) && Objects.equals(rootId, root.rootId); 219 } else { 220 return false; 221 } 222 } 223 224 @Override 225 public int hashCode() { 226 return Objects.hash(authority, rootId); 227 } 228 229 public String getDirectoryString() { 230 return !TextUtils.isEmpty(summary) ? summary : title; 231 } 232 } 233