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.server.appsearch.contactsindexer; 18 19 import android.annotation.NonNull; 20 import android.os.PersistableBundle; 21 import android.util.AtomicFile; 22 23 import com.android.internal.annotations.VisibleForTesting; 24 25 import java.io.File; 26 import java.io.FileInputStream; 27 import java.io.FileOutputStream; 28 import java.io.IOException; 29 import java.util.Objects; 30 31 /** 32 * Contacts indexer settings backed by a PersistableBundle. 33 * 34 * Holds settings such as the last time when a full update or delta update was performed. 35 * 36 * <p>This class is NOT thread safe (similar to {@link PersistableBundle} which it wraps). 37 * 38 * @hide 39 */ 40 public class ContactsIndexerSettings { 41 42 private static final String TAG = "ContactsIndexerSettings"; 43 44 /*package*/ static final String SETTINGS_FILE_NAME = "contacts_indexer_settings.pb"; 45 46 /*package*/ static final String LAST_FULL_UPDATE_TIMESTAMP_KEY = 47 "last_full_update_timestamp_millis"; 48 /*package*/ static final String LAST_DELTA_UPDATE_TIMESTAMP_KEY = 49 "last_delta_update_timestamp_millis"; 50 /*package*/ static final String LAST_DELTA_DELETE_TIMESTAMP_KEY = 51 "last_delta_delete_timestamp_millis"; 52 53 private final File mFile; 54 private PersistableBundle mBundle = new PersistableBundle(); 55 ContactsIndexerSettings(@onNull File baseDir)56 public ContactsIndexerSettings(@NonNull File baseDir) { 57 Objects.requireNonNull(baseDir); 58 mFile = new File(baseDir, SETTINGS_FILE_NAME); 59 } 60 load()61 public void load() throws IOException { 62 mBundle = readBundle(mFile); 63 } 64 persist()65 public void persist() throws IOException { 66 writeBundle(mFile, mBundle); 67 } 68 getLastFullUpdateTimestampMillis()69 public long getLastFullUpdateTimestampMillis() { 70 return mBundle.getLong(LAST_FULL_UPDATE_TIMESTAMP_KEY); 71 } 72 setLastFullUpdateTimestampMillis(long timestampMillis)73 public void setLastFullUpdateTimestampMillis(long timestampMillis) { 74 mBundle.putLong(LAST_FULL_UPDATE_TIMESTAMP_KEY, timestampMillis); 75 } 76 getLastDeltaUpdateTimestampMillis()77 public long getLastDeltaUpdateTimestampMillis() { 78 return mBundle.getLong(LAST_DELTA_UPDATE_TIMESTAMP_KEY); 79 } 80 setLastDeltaUpdateTimestampMillis(long timestampMillis)81 public void setLastDeltaUpdateTimestampMillis(long timestampMillis) { 82 mBundle.putLong(LAST_DELTA_UPDATE_TIMESTAMP_KEY, timestampMillis); 83 } 84 getLastDeltaDeleteTimestampMillis()85 public long getLastDeltaDeleteTimestampMillis() { 86 return mBundle.getLong(LAST_DELTA_DELETE_TIMESTAMP_KEY); 87 } 88 setLastDeltaDeleteTimestampMillis(long timestampMillis)89 public void setLastDeltaDeleteTimestampMillis(long timestampMillis) { 90 mBundle.putLong(LAST_DELTA_DELETE_TIMESTAMP_KEY, timestampMillis); 91 } 92 93 /** Resets all the settings to default values. */ reset()94 public void reset() { 95 setLastDeltaDeleteTimestampMillis(0); 96 setLastDeltaUpdateTimestampMillis(0); 97 setLastFullUpdateTimestampMillis(0); 98 } 99 100 @VisibleForTesting 101 @NonNull readBundle(@onNull File src)102 /*package*/ static PersistableBundle readBundle(@NonNull File src) throws 103 IOException { 104 AtomicFile atomicFile = new AtomicFile(src); 105 try (FileInputStream fis = atomicFile.openRead()) { 106 return PersistableBundle.readFromStream(fis); 107 } 108 } 109 110 @VisibleForTesting writeBundle(@onNull File dest, @NonNull PersistableBundle bundle)111 /*package*/ static void writeBundle(@NonNull File dest, @NonNull PersistableBundle bundle) 112 throws IOException { 113 AtomicFile atomicFile = new AtomicFile(dest); 114 FileOutputStream fos = null; 115 try { 116 fos = atomicFile.startWrite(); 117 bundle.writeToStream(fos); 118 atomicFile.finishWrite(fos); 119 } catch (IOException e ) { 120 if (fos != null) { 121 atomicFile.failWrite(fos); 122 } 123 throw e; 124 } 125 } 126 } 127