• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.adservices.service.common;
18 
19 import android.annotation.Nullable;
20 
21 import com.android.adservices.LoggerFactory;
22 import com.android.adservices.data.common.UserProfileIdDao;
23 import com.android.adservices.data.common.UserProfileIdDaoSharedPreferencesImpl;
24 import com.android.adservices.shared.util.Clock;
25 import com.android.internal.annotations.GuardedBy;
26 import com.android.internal.annotations.VisibleForTesting;
27 
28 import java.util.Objects;
29 import java.util.UUID;
30 
31 /** Manager of user profile id. */
32 public final class UserProfileIdManager {
33     private static final LoggerFactory.Logger LOGGER = LoggerFactory.getFledgeLogger();
34 
35     private static final Object SINGLETON_LOCK = new Object();
36 
37     private final UserProfileIdDao mUserProfileIdDao;
38     private final Clock mClock;
39 
40     @GuardedBy("SINGLETON_LOCK")
41     private static volatile UserProfileIdManager sUserProfileIdManager;
42 
43     @VisibleForTesting static final long MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24;
44 
45     @VisibleForTesting
UserProfileIdManager(final UserProfileIdDao userProfileIdDao, Clock clock)46     public UserProfileIdManager(final UserProfileIdDao userProfileIdDao, Clock clock) {
47         Objects.requireNonNull(userProfileIdDao);
48         Objects.requireNonNull(clock);
49 
50         mUserProfileIdDao = userProfileIdDao;
51         mClock = clock;
52     }
53 
54     /** Returns the singleton instance of the {@link UserProfileIdManager} */
getInstance()55     public static UserProfileIdManager getInstance() {
56         synchronized (SINGLETON_LOCK) {
57             if (sUserProfileIdManager == null) {
58                 sUserProfileIdManager =
59                         new UserProfileIdManager(
60                                 UserProfileIdDaoSharedPreferencesImpl.getInstance(),
61                                 Clock.getInstance());
62             }
63             return sUserProfileIdManager;
64         }
65     }
66 
67     /**
68      * Returns the user profile ID.
69      *
70      * <ol>
71      *   <li>If user profile ID does not exist, create and persist a new ID;
72      *   <li>Return the id in the storage.
73      * </ol>
74      */
75     @Nullable
getOrCreateId()76     public UUID getOrCreateId() {
77         UUID id = mUserProfileIdDao.getUserProfileId();
78 
79         if (id != null) {
80             return id;
81         }
82 
83         LOGGER.v("User profile ID is not present, generating a new ID.");
84         id = UUID.randomUUID();
85         mUserProfileIdDao.setUserProfileId(id);
86         return id;
87     }
88 
89     /**
90      * Clear the user profile id storage in case of consent revoke.
91      *
92      * <p>We only clear the ID if it's persisted for more than 24 hours to prevent abuse vector
93      * whereby a malicious user regenerates consentIds by toggling consent on and off
94      */
deleteId()95     public void deleteId() {
96         long lastPersistedTimestamp = mUserProfileIdDao.getTimestamp();
97         if (mClock.currentTimeMillis() >= lastPersistedTimestamp + MILLISECONDS_IN_DAY) {
98             mUserProfileIdDao.deleteStorage();
99         }
100     }
101 }
102