1 /* 2 * Copyright (C) 2022 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.providers.media.stableuris.dao; 18 19 import android.provider.MediaStore.MediaColumns; 20 21 import com.android.providers.media.util.StringUtils; 22 23 import java.io.ByteArrayInputStream; 24 import java.io.ByteArrayOutputStream; 25 import java.io.IOException; 26 import java.io.ObjectInputStream; 27 import java.io.ObjectOutputStream; 28 import java.io.Serializable; 29 import java.util.Base64; 30 import java.util.Objects; 31 32 /** 33 * DAO object representing database row of leveldb for volume database backup and recovery. 34 * 35 * Warning: Do not change/modify existing field names as it will affect deserialization of existing 36 * rows. 37 */ 38 public final class BackupIdRow implements Serializable { 39 40 private long mId; 41 private int mIsFavorite; 42 private int mIsPending; 43 private int mIsTrashed; 44 private boolean mIsDirty; 45 46 /** 47 * This is not Owner Package name but a unique identifier to it 48 */ 49 private int mOwnerPackageId; 50 51 /** 52 * Same as {@link MediaColumns#DATE_EXPIRES}. Will be null if media row does not have 53 * expiry time set. 54 */ 55 private String mDateExpires; 56 57 /** 58 * This is required to support cloned user data. 59 */ 60 private int mUserId; 61 private int mMediaType; 62 63 /** 64 * Builder class for {@link BackupIdRow} 65 */ 66 public static class Builder { 67 private long mId; 68 private int mIsFavorite; 69 private int mIsPending; 70 private int mIsTrashed; 71 private boolean mIsDirty; 72 private int mOwnerPackageId; 73 private String mDateExpires; 74 private int mUserId; 75 private int mMediaType; 76 Builder(long id)77 Builder(long id) { 78 this.mId = id; 79 } 80 81 /** 82 * Sets the isFavorite value 83 */ setIsFavorite(int isFavorite)84 public Builder setIsFavorite(int isFavorite) { 85 this.mIsFavorite = isFavorite; 86 return this; 87 } 88 89 /** 90 * Sets the isPending value 91 */ setIsPending(int isPending)92 public Builder setIsPending(int isPending) { 93 this.mIsPending = isPending; 94 return this; 95 } 96 97 /** 98 * Sets the isTrashed value 99 */ setIsTrashed(int isTrashed)100 public Builder setIsTrashed(int isTrashed) { 101 this.mIsTrashed = isTrashed; 102 return this; 103 } 104 105 /** 106 * Sets the ownerPackagedId value 107 */ setOwnerPackagedId(int ownerPackagedId)108 public Builder setOwnerPackagedId(int ownerPackagedId) { 109 this.mOwnerPackageId = ownerPackagedId; 110 return this; 111 } 112 113 /** 114 * Sets the dateExpires value 115 */ setDateExpires(String dateExpires)116 public Builder setDateExpires(String dateExpires) { 117 if (StringUtils.isNullOrEmpty(dateExpires)) { 118 this.mDateExpires = null; 119 } else { 120 long value = Long.parseLong(dateExpires); 121 this.mDateExpires = String.valueOf(value); 122 } 123 124 return this; 125 } 126 127 /** 128 * Sets the userId value 129 */ setUserId(int userId)130 public Builder setUserId(int userId) { 131 this.mUserId = userId; 132 return this; 133 } 134 135 /** 136 * Sets the mediatype value 137 */ setMediaType(int mediaType)138 public Builder setMediaType(int mediaType) { 139 this.mMediaType = mediaType; 140 return this; 141 } 142 143 /** 144 * Sets the isDirty value 145 */ setIsDirty(boolean isDirty)146 public Builder setIsDirty(boolean isDirty) { 147 this.mIsDirty = isDirty; 148 return this; 149 } 150 151 /** 152 * Builds {@link BackupIdRow} object with the given values set 153 */ build()154 public BackupIdRow build() { 155 BackupIdRow backupIdRow = new BackupIdRow(this.mId); 156 backupIdRow.mIsFavorite = this.mIsFavorite; 157 backupIdRow.mIsPending = this.mIsPending; 158 backupIdRow.mIsTrashed = this.mIsTrashed; 159 backupIdRow.mIsDirty = this.mIsDirty; 160 backupIdRow.mOwnerPackageId = this.mOwnerPackageId; 161 backupIdRow.mDateExpires = this.mDateExpires; 162 backupIdRow.mUserId = this.mUserId; 163 backupIdRow.mMediaType = this.mMediaType; 164 165 return backupIdRow; 166 } 167 } 168 newBuilder(long id)169 public static Builder newBuilder(long id) { 170 return new BackupIdRow.Builder(id); 171 } 172 BackupIdRow(long id)173 private BackupIdRow(long id) { 174 this.mId = id; 175 } 176 getId()177 public long getId() { 178 return mId; 179 } 180 getIsFavorite()181 public int getIsFavorite() { 182 return mIsFavorite; 183 } 184 getIsPending()185 public int getIsPending() { 186 return mIsPending; 187 } 188 getIsTrashed()189 public int getIsTrashed() { 190 return mIsTrashed; 191 } 192 getOwnerPackageId()193 public int getOwnerPackageId() { 194 return mOwnerPackageId; 195 } 196 getUserId()197 public int getUserId() { 198 return mUserId; 199 } 200 getDateExpires()201 public String getDateExpires() { 202 return mDateExpires; 203 } 204 getIsDirty()205 public boolean getIsDirty() { 206 return mIsDirty; 207 } 208 getMediaType()209 public int getMediaType() { 210 return mMediaType; 211 } 212 213 /** 214 * Returns human-readable form of {@link BackupIdRow} for easy debugging. 215 */ 216 @Override toString()217 public String toString() { 218 return "BackupIdRow{" + 219 "mId=" + mId + 220 ", mIsFavorite=" + mIsFavorite + 221 ", mIsPending=" + mIsPending + 222 ", mIsTrashed=" + mIsTrashed + 223 ", mIsDirty=" + mIsDirty + 224 ", mOwnerPackageId=" + mOwnerPackageId + 225 ", mDateExpires=" + mDateExpires + 226 ", mUserId=" + mUserId + 227 ", mMediaType=" + mMediaType + 228 '}'; 229 } 230 231 @Override equals(Object o)232 public boolean equals(Object o) { 233 if (this == o) return true; 234 if (!(o instanceof BackupIdRow)) return false; 235 BackupIdRow that = (BackupIdRow) o; 236 return mId == that.mId && mIsFavorite == that.mIsFavorite && mIsPending == that.mIsPending 237 && mIsTrashed == that.mIsTrashed && mIsDirty == that.mIsDirty 238 && mOwnerPackageId == that.mOwnerPackageId && mUserId == that.mUserId 239 && mMediaType == that.mMediaType && Objects.equals(mDateExpires, 240 that.mDateExpires); 241 } 242 243 @Override hashCode()244 public int hashCode() { 245 return Objects.hash(mId, mIsFavorite, mIsPending, mIsTrashed, mIsDirty, mOwnerPackageId, 246 mDateExpires, mUserId, mMediaType); 247 } 248 249 /** 250 * Serializes the given {@link BackupIdRow} object to a string 251 */ serialize(BackupIdRow backupIdRow)252 public static String serialize(BackupIdRow backupIdRow) throws IOException { 253 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 254 ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 255 objectOutputStream.writeObject(backupIdRow); 256 objectOutputStream.close(); 257 return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()); 258 } 259 260 /** 261 * Deserializes the given string to {@link BackupIdRow} object 262 */ deserialize(String s)263 public static BackupIdRow deserialize(String s) throws IOException, ClassNotFoundException { 264 byte[] bytes = Base64.getDecoder().decode(s); 265 ObjectInputStream objectInputStream = new ObjectInputStream( 266 new ByteArrayInputStream(bytes)); 267 BackupIdRow backupIdRow = (BackupIdRow) objectInputStream.readObject(); 268 objectInputStream.close(); 269 return backupIdRow; 270 } 271 } 272