1515package  com .google .firebase .heartbeatinfo ;
1616
1717import  android .content .Context ;
18- import  android .content .SharedPreferences ;
1918import  android .os .Build ;
2019import  androidx .annotation .RestrictTo ;
2120import  androidx .annotation .VisibleForTesting ;
21+ import  androidx .datastore .preferences .core .*;
22+ import  androidx .datastore .preferences .core .Preferences ;
23+ import  com .google .firebase .datastore .DataStorage ;
24+ import  com .google .firebase .datastore .DataStoreKt ;
2225import  java .text .SimpleDateFormat ;
2326import  java .time .Instant ;
2427import  java .time .LocalDateTime ;
4043class  HeartBeatInfoStorage  {
4144  private  static  HeartBeatInfoStorage  instance  = null ;
4245
43-   private  static  final  String  GLOBAL  = "fire-global" ;
46+   private  static  final  Preferences . Key < Long >  GLOBAL  = PreferencesKeys . longKey ( "fire-global" ) ;
4447
4548  private  static  final  String  PREFERENCES_NAME  = "FirebaseAppHeartBeat" ;
4649
4750  private  static  final  String  HEARTBEAT_PREFERENCES_NAME  = "FirebaseHeartBeat" ;
4851
49-   private  static  final  String  HEART_BEAT_COUNT_TAG  = "fire-count" ;
52+   private  static  final  Preferences .Key <Long > HEART_BEAT_COUNT_TAG  =
53+       PreferencesKeys .longKey ("fire-count" );
5054
51-   private  static  final  String  LAST_STORED_DATE  = "last-used-date" ;
55+   private  static  final  Preferences .Key <String > LAST_STORED_DATE  =
56+       PreferencesKeys .stringKey ("last-used-date" );
5257
5358  // As soon as you hit the limit of heartbeats. The number of stored heartbeats is halved. 
5459  private  static  final  int  HEART_BEAT_COUNT_LIMIT  = 30 ;
5560
56-   private  final  SharedPreferences   firebaseSharedPreferences ;
61+   private  final  DataStorage   firebaseDataStore ;
5762
5863  public  HeartBeatInfoStorage (Context  applicationContext , String  persistenceKey ) {
59-     this .firebaseSharedPreferences  =
60-         applicationContext .getSharedPreferences (
61-             HEARTBEAT_PREFERENCES_NAME  + persistenceKey , Context .MODE_PRIVATE );
64+     this .firebaseDataStore  =
65+         new  DataStorage (applicationContext , HEARTBEAT_PREFERENCES_NAME  + persistenceKey );
6266  }
6367
6468  @ VisibleForTesting 
6569  @ RestrictTo (RestrictTo .Scope .TESTS )
66-   HeartBeatInfoStorage (SharedPreferences   firebaseSharedPreferences ) {
67-     this .firebaseSharedPreferences  = firebaseSharedPreferences ;
70+   HeartBeatInfoStorage (DataStorage   dataStorage ) {
71+     this .firebaseDataStore  = dataStorage ;
6872  }
6973
7074  @ VisibleForTesting 
7175  @ RestrictTo (RestrictTo .Scope .TESTS )
7276  int  getHeartBeatCount () {
73-     return  ( int )  this .firebaseSharedPreferences . getLong (HEART_BEAT_COUNT_TAG , 0 );
77+     return  this .firebaseDataStore . getSync (HEART_BEAT_COUNT_TAG , 0L ). intValue ( );
7478  }
7579
7680  synchronized  void  deleteAllHeartBeats () {
77-     SharedPreferences . Editor   editor  =  firebaseSharedPreferences . edit (); 
78-     int   counter  =  0 ; 
79-     for  ( Map . Entry < String , ?>  entry  :  this . firebaseSharedPreferences . getAll (). entrySet ()) { 
80-       if  ( entry . getValue ()  instanceof   Set ) {
81-         // All other heartbeats other than the heartbeats stored today will be deleted. 
82-         Set < String >  dates  = ( Set < String >)  entry . getValue (); 
83-         String   today  = getFormattedDate ( System . currentTimeMillis () );
84-         String   key  = entry .getKey ();
85-         if  ( dates . contains ( today )) { 
86-            Set < String >  userAgentDateSet  =  new   HashSet <>(); 
87-           userAgentDateSet . add (today ); 
88-           counter  +=  1 ;
89-           editor . putStringSet ( key ,  userAgentDateSet ) ;
90-         } else  {
91-           editor .remove (key );
92-         }
93-       }
94-     }
95-     if  (counter  == 0 ) {
96-       editor .remove (HEART_BEAT_COUNT_TAG );
97-     } else  {
98-       editor . putLong (HEART_BEAT_COUNT_TAG , counter );
99-     }
81+     firebaseDataStore . editSync ( 
82+         ( pref ) -> { 
83+            long   counter  =  0 ; 
84+            for  ( Map . Entry < Preferences . Key <?>,  Object >  entry  :  pref . asMap (). entrySet () ) {
85+              if  ( entry . getValue ()  instanceof   Set ) { 
86+                // All other heartbeats other than the heartbeats stored today will be deleted. 
87+                Preferences . Key < Set < String >>  key  = ( Preferences . Key < Set < String >>)  entry . getKey ( );
88+                Set < String >  dates  = ( Set < String >)  entry .getValue ();
89+                String   today  =  getFormattedDate ( System . currentTimeMillis ()); 
90+ 
91+                if  ( dates . contains (today )) { 
92+                  pref . set ( key ,  Set . of ( today )) ;
93+                  counter  +=  1 ;
94+                } else  {
95+                  pref .remove (key );
96+                }
97+              }
98+            }
99+            if  (counter  == 0 ) {
100+              pref .remove (HEART_BEAT_COUNT_TAG );
101+            } else  {
102+              pref . set (HEART_BEAT_COUNT_TAG , counter );
103+            }
100104
101-     editor .commit ();
105+           return  null ;
106+         });
102107  }
103108
104109  synchronized  List <HeartBeatResult > getAllHeartBeats () {
105110    ArrayList <HeartBeatResult > heartBeatResults  = new  ArrayList <>();
106-     for  (Map .Entry <String , ?> entry  : this .firebaseSharedPreferences .getAll ().entrySet ()) {
111+     String  today  = getFormattedDate (System .currentTimeMillis ());
112+ 
113+     for  (Map .Entry <Preferences .Key <?>, Object > entry  :
114+         this .firebaseDataStore .getAllSync ().entrySet ()) {
107115      if  (entry .getValue () instanceof  Set ) {
108116        Set <String > dates  = new  HashSet <>((Set <String >) entry .getValue ());
109-         String  today  = getFormattedDate (System .currentTimeMillis ());
110117        dates .remove (today );
111118        if  (!dates .isEmpty ()) {
112-           heartBeatResults .add (
113-               HeartBeatResult .create (entry .getKey (), new  ArrayList <String >(dates )));
119+           heartBeatResults .add (HeartBeatResult .create (entry .getKey ().getName (), new  ArrayList <>()));
114120        }
115121      }
116122    }
123+ 
117124    updateGlobalHeartBeat (System .currentTimeMillis ());
125+ 
118126    return  heartBeatResults ;
119127  }
120128
121-   private  synchronized  String  getStoredUserAgentString (String  dateString ) {
122-     for  (Map .Entry <String , ?> entry  : firebaseSharedPreferences .getAll ().entrySet ()) {
129+   private  synchronized  Preferences .Key <Set <String >> getStoredUserAgentString (
130+       MutablePreferences  preferences , String  dateString ) {
131+     for  (Map .Entry <Preferences .Key <?>, Object > entry  : preferences .asMap ().entrySet ()) {
123132      if  (entry .getValue () instanceof  Set ) {
124133        Set <String > dateSet  = (Set <String >) entry .getValue ();
125134        for  (String  date  : dateSet ) {
126135          if  (dateString .equals (date )) {
127-             return  entry .getKey ();
136+             return  PreferencesKeys . stringSetKey ( entry .getKey (). getName () );
128137          }
129138        }
130139      }
131140    }
132141    return  null ;
133142  }
134143
135-   private  synchronized  void  updateStoredUserAgent (String  userAgent , String  dateString ) {
136-     removeStoredDate (dateString );
144+   private  synchronized  void  updateStoredUserAgent (
145+       MutablePreferences  preferences , Preferences .Key <Set <String >> userAgent , String  dateString ) {
146+     removeStoredDate (preferences , dateString );
137147    Set <String > userAgentDateSet  =
138-         new  HashSet <String >(
139-             firebaseSharedPreferences .getStringSet (userAgent , new  HashSet <String >()));
148+         new  HashSet <>(DataStoreKt .getOrDefault (preferences , userAgent , new  HashSet <>()));
140149    userAgentDateSet .add (dateString );
141-     firebaseSharedPreferences . edit (). putStringSet ( userAgent , userAgentDateSet ). commit ( );
150+     preferences . set ( userAgent , userAgentDateSet );
142151  }
143152
144-   private  synchronized  void  removeStoredDate (String  dateString ) {
153+   private  synchronized  void  removeStoredDate (MutablePreferences   preferences ,  String  dateString ) {
145154    // Find stored heartbeat and clear it. 
146-     String   userAgentString  = getStoredUserAgentString (dateString );
147-     if  (userAgentString  == null ) {
155+     Preferences . Key < Set < String >>  userAgent  = getStoredUserAgentString (preferences ,  dateString );
156+     if  (userAgent  == null ) {
148157      return ;
149158    }
150159    Set <String > userAgentDateSet  =
151-         new  HashSet <String >(
152-             firebaseSharedPreferences .getStringSet (userAgentString , new  HashSet <String >()));
160+         new  HashSet <>(DataStoreKt .getOrDefault (preferences , userAgent , new  HashSet <>()));
153161    userAgentDateSet .remove (dateString );
154162    if  (userAgentDateSet .isEmpty ()) {
155-       firebaseSharedPreferences . edit (). remove (userAgentString ). commit ( );
163+       preferences . remove (userAgent );
156164    } else  {
157-       firebaseSharedPreferences . edit (). putStringSet ( userAgentString , userAgentDateSet ). commit ( );
165+       preferences . set ( userAgent , userAgentDateSet );
158166    }
159167  }
160168
161169  synchronized  void  postHeartBeatCleanUp () {
162170    String  dateString  = getFormattedDate (System .currentTimeMillis ());
163-     firebaseSharedPreferences .edit ().putString (LAST_STORED_DATE , dateString ).commit ();
164-     removeStoredDate (dateString );
171+ 
172+     firebaseDataStore .editSync (
173+         (pref ) -> {
174+           pref .set (LAST_STORED_DATE , dateString );
175+           removeStoredDate (pref , dateString );
176+           return  null ;
177+         });
165178  }
166179
167180  private  synchronized  String  getFormattedDate (long  millis ) {
@@ -176,71 +189,77 @@ private synchronized String getFormattedDate(long millis) {
176189
177190  synchronized  void  storeHeartBeat (long  millis , String  userAgentString ) {
178191    String  dateString  = getFormattedDate (millis );
179-     String  lastDateString  = firebaseSharedPreferences .getString (LAST_STORED_DATE , "" );
180-     if  (lastDateString .equals (dateString )) {
181-       String  storedUserAgentString  = getStoredUserAgentString (dateString );
182-       if  (storedUserAgentString  == null ) {
183-         // Heartbeat already sent for today. 
184-         return ;
185-       }
186-       if  (storedUserAgentString .equals (userAgentString )) {
187-         // UserAgent not updated. 
188-         return ;
189-       } else  {
190-         updateStoredUserAgent (userAgentString , dateString );
191-         return ;
192-       }
193-     }
194-     long  heartBeatCount  = firebaseSharedPreferences .getLong (HEART_BEAT_COUNT_TAG , 0 );
195-     if  (heartBeatCount  + 1  == HEART_BEAT_COUNT_LIMIT ) {
196-       cleanUpStoredHeartBeats ();
197-       heartBeatCount  = firebaseSharedPreferences .getLong (HEART_BEAT_COUNT_TAG , 0 );
198-     }
199-     Set <String > userAgentDateSet  =
200-         new  HashSet <String >(
201-             firebaseSharedPreferences .getStringSet (userAgentString , new  HashSet <String >()));
202-     userAgentDateSet .add (dateString );
203-     heartBeatCount  += 1 ;
204-     firebaseSharedPreferences 
205-         .edit ()
206-         .putStringSet (userAgentString , userAgentDateSet )
207-         .putLong (HEART_BEAT_COUNT_TAG , heartBeatCount )
208-         .putString (LAST_STORED_DATE , dateString )
209-         .commit ();
192+     Preferences .Key <Set <String >> userAgent  = PreferencesKeys .stringSetKey (userAgentString );
193+     firebaseDataStore .editSync (
194+         (pref ) -> {
195+           String  lastDateString  = DataStoreKt .getOrDefault (pref , LAST_STORED_DATE , "" );
196+           if  (lastDateString .equals (dateString )) {
197+             Preferences .Key <Set <String >> storedUserAgent  =
198+                 getStoredUserAgentString (pref , dateString );
199+             if  (storedUserAgent  == null ) {
200+               // Heartbeat already sent for today. 
201+               return  null ;
202+             } else  if  (storedUserAgent .getName ().equals (userAgentString )) {
203+               // UserAgent not updated. 
204+               return  null ;
205+             } else  {
206+               updateStoredUserAgent (pref , userAgent , dateString );
207+               return  null ;
208+             }
209+           }
210+           long  heartBeatCount  = DataStoreKt .getOrDefault (pref , HEART_BEAT_COUNT_TAG , 0L );
211+           if  (heartBeatCount  + 1  == HEART_BEAT_COUNT_LIMIT ) {
212+             heartBeatCount  = cleanUpStoredHeartBeats (pref );
213+           }
214+           Set <String > userAgentDateSet  =
215+               new  HashSet <>(DataStoreKt .getOrDefault (pref , userAgent , new  HashSet <>()));
216+           userAgentDateSet .add (dateString );
217+           heartBeatCount  += 1 ;
218+ 
219+           pref .set (userAgent , userAgentDateSet );
220+           pref .set (HEART_BEAT_COUNT_TAG , heartBeatCount );
221+           pref .set (LAST_STORED_DATE , dateString );
222+ 
223+           return  null ;
224+         });
210225  }
211226
212-   private  synchronized  void  cleanUpStoredHeartBeats () {
213-     long  heartBeatCount  = firebaseSharedPreferences .getLong (HEART_BEAT_COUNT_TAG , 0 );
227+   private  synchronized  long  cleanUpStoredHeartBeats (MutablePreferences  preferences ) {
228+     long  heartBeatCount  = DataStoreKt .getOrDefault (preferences , HEART_BEAT_COUNT_TAG , 0L );
229+ 
214230    String  lowestDate  = null ;
215231    String  userAgentString  = "" ;
216-     for  (Map .Entry <String , ?> entry  : firebaseSharedPreferences .getAll ().entrySet ()) {
232+     Set <String > userAgentDateSet  = new  HashSet <>();
233+     for  (Map .Entry <Preferences .Key <?>, Object > entry  : preferences .asMap ().entrySet ()) {
217234      if  (entry .getValue () instanceof  Set ) {
218235        Set <String > dateSet  = (Set <String >) entry .getValue ();
219236        for  (String  date  : dateSet ) {
220237          if  (lowestDate  == null  || lowestDate .compareTo (date ) > 0 ) {
238+             userAgentDateSet  = dateSet ;
221239            lowestDate  = date ;
222-             userAgentString  = entry .getKey ();
240+             userAgentString  = entry .getKey (). getName () ;
223241          }
224242        }
225243      }
226244    }
227-     Set <String > userAgentDateSet  =
228-         new  HashSet <String >(
229-             firebaseSharedPreferences .getStringSet (userAgentString , new  HashSet <String >()));
245+     userAgentDateSet  = new  HashSet <>(userAgentDateSet );
230246    userAgentDateSet .remove (lowestDate );
231-     firebaseSharedPreferences 
232-         .edit ()
233-         .putStringSet (userAgentString , userAgentDateSet )
234-         .putLong (HEART_BEAT_COUNT_TAG , heartBeatCount  - 1 )
235-         .commit ();
247+     preferences .set (PreferencesKeys .stringSetKey (userAgentString ), userAgentDateSet );
248+     preferences .set (HEART_BEAT_COUNT_TAG , heartBeatCount  - 1 );
249+ 
250+     return  heartBeatCount  - 1 ;
236251  }
237252
238253  synchronized  long  getLastGlobalHeartBeat () {
239-     return  firebaseSharedPreferences . getLong (GLOBAL , -1 );
254+     return  firebaseDataStore . getSync (GLOBAL , -1L );
240255  }
241256
242257  synchronized  void  updateGlobalHeartBeat (long  millis ) {
243-     firebaseSharedPreferences .edit ().putLong (GLOBAL , millis ).commit ();
258+     firebaseDataStore .editSync (
259+         (pref ) -> {
260+           pref .set (GLOBAL , millis );
261+           return  null ;
262+         });
244263  }
245264
246265  synchronized  boolean  isSameDateUtc (long  base , long  target ) {
@@ -252,15 +271,11 @@ synchronized boolean isSameDateUtc(long base, long target) {
252271   A sdk heartbeat is sent either when there is no heartbeat sent ever for the sdk or 
253272   when the last heartbeat send for the sdk was later than a day before. 
254273  */ 
255-   synchronized  boolean  shouldSendSdkHeartBeat (String  heartBeatTag , long  millis ) {
256-     if  (firebaseSharedPreferences .contains (heartBeatTag )) {
257-       if  (!this .isSameDateUtc (firebaseSharedPreferences .getLong (heartBeatTag , -1 ), millis )) {
258-         firebaseSharedPreferences .edit ().putLong (heartBeatTag , millis ).commit ();
259-         return  true ;
260-       }
274+   synchronized  boolean  shouldSendSdkHeartBeat (Preferences .Key <Long > heartBeatTag , long  millis ) {
275+     if  (this .isSameDateUtc (firebaseDataStore .getSync (heartBeatTag , -1L ), millis )) {
261276      return  false ;
262277    } else  {
263-       firebaseSharedPreferences . edit (). putLong ( heartBeatTag , millis ). commit ( );
278+       firebaseDataStore . putSync ( heartBeatTag , millis );
264279      return  true ;
265280    }
266281  }
0 commit comments