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