• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 android.util;
18 
19 /**
20  * Utilities to manage an info change seq id to ensure the update is in sync between client and
21  * system server. This should be used for info that can be updated though multiple IPC channel.
22  *
23  * To use it:
24  * 1. The system server should store the current seq as the source of truth, with initializing to
25  * {@link #getInitSeq}.
26  * 2. Whenever a newer info needs to be sent to the client side, the system server should first
27  * update its seq with {@link #getNextSeq}, then send the new info with the new seq to the client.
28  * 3. On the client side, when receiving a new info, it should only consume it if it is not stale by
29  * checking {@link #isIncomingSeqStale}.
30  *
31  * @hide
32  */
33 public final class SequenceUtils {
34 
SequenceUtils()35     private SequenceUtils() {
36     }
37 
38     /**
39      * Returns {@code true} if the incomingSeq is stale, which means the client should not consume
40      * it.
41      */
isIncomingSeqStale(int curSeq, int incomingSeq)42     public static boolean isIncomingSeqStale(int curSeq, int incomingSeq) {
43         if (curSeq == getInitSeq()) {
44             // curSeq can be set to the initial seq in the following cases:
45             // 1. The client process/field is newly created/recreated.
46             // 2. The field is not managed by the system server, such as WindowlessWindowManager.
47             // The client should always consume the incoming in these cases.
48             return false;
49         }
50         // Convert to long for comparison.
51         final long diff = (long) incomingSeq - curSeq;
52         // When diff is 0, allow client to consume.
53         // When there has been a sufficiently large jump, assume the sequence has wrapped around.
54         return (diff < 0 && diff > Integer.MIN_VALUE) || diff > Integer.MAX_VALUE;
55     }
56 
57     /** Returns the initial seq. */
getInitSeq()58     public static int getInitSeq() {
59         return Integer.MIN_VALUE;
60     }
61 
62     /** Returns the next seq. */
getNextSeq(int seq)63     public static int getNextSeq(int seq) {
64         return seq == Integer.MAX_VALUE
65                 // Skip the initial seq, so that when the app process is relaunched, the incoming
66                 // seq from the server is always treated as newer.
67                 ? getInitSeq() + 1
68                 : ++seq;
69     }
70 }
71