1b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro/*
2b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * Copyright 2017 The Android Open Source Project
3b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro *
4b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * Licensed under the Apache License, Version 2.0 (the "License");
5b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * you may not use this file except in compliance with the License.
6b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * You may obtain a copy of the License at
7b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro *
8b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro *      http://www.apache.org/licenses/LICENSE-2.0
9b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro *
10b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * Unless required by applicable law or agreed to in writing, software
11b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * distributed under the License is distributed on an "AS IS" BASIS,
12b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * See the License for the specific language governing permissions and
14b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * limitations under the License.
15b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro */
16b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguropackage android.hardware.location;
17b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
18e35a6debaaec952800cf74020886e6bb50618f7dArthur Ishiguroimport android.annotation.CallbackExecutor;
19b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguroimport android.annotation.IntDef;
206c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguroimport android.annotation.NonNull;
21f2b6f014a7c44f5828dfee88d6f3592fa50b64e4Arthur Ishiguroimport android.annotation.SystemApi;
22b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguroimport android.os.Handler;
23e35a6debaaec952800cf74020886e6bb50618f7dArthur Ishiguroimport android.os.HandlerExecutor;
24b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
25ac7b959be1fb268a3e387b57df0ee7b1e52b7cc3Arthur Ishiguroimport com.android.internal.util.Preconditions;
26ac7b959be1fb268a3e387b57df0ee7b1e52b7cc3Arthur Ishiguro
27b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguroimport java.lang.annotation.Retention;
28b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguroimport java.lang.annotation.RetentionPolicy;
296c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguroimport java.util.concurrent.CountDownLatch;
30e35a6debaaec952800cf74020886e6bb50618f7dArthur Ishiguroimport java.util.concurrent.Executor;
31b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguroimport java.util.concurrent.TimeUnit;
326c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguroimport java.util.concurrent.TimeoutException;
33b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
34b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro/**
35b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * A class describing a request sent to the Context Hub Service.
36b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro *
37b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * This object is generated as a result of an asynchronous request sent to the Context Hub
38b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * through the ContextHubManager APIs. The caller can either retrieve the result
39b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * synchronously through a blocking call ({@link #waitForResponse(long, TimeUnit)}) or
40ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro * asynchronously through a user-defined listener
41b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro * ({@link #setOnCompleteListener(OnCompleteListener, Executor)} )}).
42b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro *
43b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * @param <T> the type of the contents in the transaction response
44b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro *
45b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro * @hide
46b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro */
47f2b6f014a7c44f5828dfee88d6f3592fa50b64e4Arthur Ishiguro@SystemApi
48b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguropublic class ContextHubTransaction<T> {
496c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    private static final String TAG = "ContextHubTransaction";
506c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
51b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
52b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * Constants describing the type of a transaction through the Context Hub Service.
53f2b6f014a7c44f5828dfee88d6f3592fa50b64e4Arthur Ishiguro     * {@hide}
54b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
55b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    @Retention(RetentionPolicy.SOURCE)
56ce8db9911494225fcd99711d7df85a130de5a6ceJeff Sharkey    @IntDef(prefix = { "TYPE_" }, value = {
57b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro            TYPE_LOAD_NANOAPP,
58b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro            TYPE_UNLOAD_NANOAPP,
59b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro            TYPE_ENABLE_NANOAPP,
60b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro            TYPE_DISABLE_NANOAPP,
61ce8db9911494225fcd99711d7df85a130de5a6ceJeff Sharkey            TYPE_QUERY_NANOAPPS
62ce8db9911494225fcd99711d7df85a130de5a6ceJeff Sharkey    })
63ce8db9911494225fcd99711d7df85a130de5a6ceJeff Sharkey    public @interface Type { }
64ce8db9911494225fcd99711d7df85a130de5a6ceJeff Sharkey
65b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    public static final int TYPE_LOAD_NANOAPP = 0;
66b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    public static final int TYPE_UNLOAD_NANOAPP = 1;
67b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    public static final int TYPE_ENABLE_NANOAPP = 2;
68b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    public static final int TYPE_DISABLE_NANOAPP = 3;
69b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    public static final int TYPE_QUERY_NANOAPPS = 4;
70b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
71b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
72b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * Constants describing the result of a transaction or request through the Context Hub Service.
73f2b6f014a7c44f5828dfee88d6f3592fa50b64e4Arthur Ishiguro     * {@hide}
74b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
75b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    @Retention(RetentionPolicy.SOURCE)
766100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro    @IntDef(prefix = { "RESULT_" }, value = {
776100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro            RESULT_SUCCESS,
786100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro            RESULT_FAILED_UNKNOWN,
796100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro            RESULT_FAILED_BAD_PARAMS,
806100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro            RESULT_FAILED_UNINITIALIZED,
81f3691da800fedb320b8c4c769dbc294440007388Arthur Ishiguro            RESULT_FAILED_BUSY,
826100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro            RESULT_FAILED_AT_HUB,
836100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro            RESULT_FAILED_TIMEOUT,
846100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro            RESULT_FAILED_SERVICE_INTERNAL_FAILURE,
856100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro            RESULT_FAILED_HAL_UNAVAILABLE
86ce8db9911494225fcd99711d7df85a130de5a6ceJeff Sharkey    })
87b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    public @interface Result {}
886100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro    public static final int RESULT_SUCCESS = 0;
89b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
90b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * Generic failure mode.
91b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
926100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro    public static final int RESULT_FAILED_UNKNOWN = 1;
93b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
94b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * Failure mode when the request parameters were not valid.
95b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
966100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro    public static final int RESULT_FAILED_BAD_PARAMS = 2;
97b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
98b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * Failure mode when the Context Hub is not initialized.
99b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
1006100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro    public static final int RESULT_FAILED_UNINITIALIZED = 3;
101b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
102b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * Failure mode when there are too many transactions pending.
103b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
104f3691da800fedb320b8c4c769dbc294440007388Arthur Ishiguro    public static final int RESULT_FAILED_BUSY = 4;
105b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
106b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * Failure mode when the request went through, but failed asynchronously at the hub.
107b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
1086100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro    public static final int RESULT_FAILED_AT_HUB = 5;
109b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
110b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * Failure mode when the transaction has timed out.
111b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
1126100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro    public static final int RESULT_FAILED_TIMEOUT = 6;
1136c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    /**
1146c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * Failure mode when the transaction has failed internally at the service.
1156c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     */
1166100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro    public static final int RESULT_FAILED_SERVICE_INTERNAL_FAILURE = 7;
117e1ade4368f8b3739e93bc3f6aefabda8b2b4424cArthur Ishiguro    /**
118e1ade4368f8b3739e93bc3f6aefabda8b2b4424cArthur Ishiguro     * Failure mode when the Context Hub HAL was not available.
119e1ade4368f8b3739e93bc3f6aefabda8b2b4424cArthur Ishiguro     */
1206100aa7e72c0506b612b575fe0cb67479710eaa4Arthur Ishiguro    public static final int RESULT_FAILED_HAL_UNAVAILABLE = 8;
121b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
122b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
123b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * A class describing the response for a ContextHubTransaction.
124b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     *
125b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * @param <R> the type of the contents in the response
126b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
127b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    public static class Response<R> {
128b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        /*
129b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro         * The result of the transaction.
130b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro         */
131b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        @ContextHubTransaction.Result
132b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        private int mResult;
133b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
134b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        /*
135b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro         * The contents of the response from the Context Hub.
136b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro         */
137b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        private R mContents;
138b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
139b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        Response(@ContextHubTransaction.Result int result, R contents) {
140b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro            mResult = result;
141b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro            mContents = contents;
142b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        }
143b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
144b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        @ContextHubTransaction.Result
145b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        public int getResult() {
146b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro            return mResult;
147b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        }
148b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
149b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        public R getContents() {
150b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro            return mContents;
151b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        }
152b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    }
153b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
154b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
155ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * An interface describing the listener for a transaction completion.
156b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     *
157ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * @param <L> the type of the contents in the transaction response
158b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
159b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    @FunctionalInterface
160b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro    public interface OnCompleteListener<L> {
161b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        /**
162ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro         * The listener function to invoke when the transaction completes.
163b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro         *
164b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro         * @param transaction the transaction that this callback was attached to.
165b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro         * @param response the response of the transaction.
166b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro         */
167b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        void onComplete(
168ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro                ContextHubTransaction<L> transaction, ContextHubTransaction.Response<L> response);
169b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    }
170b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
171b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /*
172b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * The type of the transaction.
173b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
174b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    @Type
175b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    private int mTransactionType;
176b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
177b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /*
178b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * The response of the transaction.
179b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
180b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    private ContextHubTransaction.Response<T> mResponse;
181b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
182b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /*
183e35a6debaaec952800cf74020886e6bb50618f7dArthur Ishiguro     * The executor to invoke the onComplete async callback.
184b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
185e35a6debaaec952800cf74020886e6bb50618f7dArthur Ishiguro    private Executor mExecutor = null;
186b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
187b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /*
188ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * The listener to be invoked when the transaction completes.
189b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
190b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro    private ContextHubTransaction.OnCompleteListener<T> mListener = null;
191b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
1926c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    /*
1936c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * Synchronization latch used to block on response.
1946c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     */
1956c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    private final CountDownLatch mDoneSignal = new CountDownLatch(1);
1966c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
1976c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    /*
1986c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * true if the response has been set throught setResponse, false otherwise.
1996c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     */
2006c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    private boolean mIsResponseSet = false;
2016c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
2026c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    ContextHubTransaction(@Type int type) {
203b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        mTransactionType = type;
204b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    }
205b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
206b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
2074493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro     * Converts a transaction type to a human-readable string
2084493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro     *
2094493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro     * @param type the type of a transaction
2104493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro     * @param upperCase {@code true} if upper case the first letter, {@code false} otherwise
2114493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro     * @return a string describing the transaction
2124493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro     */
2134493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro    public static String typeToString(@Type int type, boolean upperCase) {
2144493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro        switch (type) {
2154493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro            case ContextHubTransaction.TYPE_LOAD_NANOAPP:
2164493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro                return upperCase ? "Load" : "load";
2174493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro            case ContextHubTransaction.TYPE_UNLOAD_NANOAPP:
2184493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro                return upperCase ? "Unload" : "unload";
2194493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro            case ContextHubTransaction.TYPE_ENABLE_NANOAPP:
2204493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro                return upperCase ? "Enable" : "enable";
2214493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro            case ContextHubTransaction.TYPE_DISABLE_NANOAPP:
2224493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro                return upperCase ? "Disable" : "disable";
2234493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro            case ContextHubTransaction.TYPE_QUERY_NANOAPPS:
2244493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro                return upperCase ? "Query" : "query";
2254493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro            default:
2264493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro                return upperCase ? "Unknown" : "unknown";
2274493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro        }
2284493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro    }
2294493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro
2304493e1498455147a4aefc3c0a8534e43d64177c3Arthur Ishiguro    /**
231b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * @return the type of the transaction
232b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
233b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    @Type
234b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    public int getType() {
235b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro        return mTransactionType;
236b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    }
237b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
238b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
239b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * Waits to receive the asynchronous transaction result.
240b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     *
241b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * This function blocks until the Context Hub Service has received a response
242b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * for the transaction represented by this object by the Context Hub, or a
243b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * specified timeout period has elapsed.
244b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     *
2456c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * If the specified timeout has passed, a TimeoutException will be thrown and the caller may
2466c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * retry the invocation of this method at a later time.
247b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     *
248b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * @param timeout the timeout duration
249b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * @param unit the unit of the timeout
250b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     *
251b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * @return the transaction response
2526c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
2536c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * @throws InterruptedException if the current thread is interrupted while waiting for response
2546c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * @throws TimeoutException if the timeout period has passed
255b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
2566c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    public ContextHubTransaction.Response<T> waitForResponse(
2576c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
2586c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro        boolean success = mDoneSignal.await(timeout, unit);
2596c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
2606c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro        if (!success) {
2616c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            throw new TimeoutException("Timed out while waiting for transaction");
2626c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro        }
2636c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
2646c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro        return mResponse;
265b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    }
266b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
267b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    /**
268ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * Sets the listener to be invoked invoked when the transaction completes.
269b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     *
270b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * This function provides an asynchronous approach to retrieve the result of the
271b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     * transaction. When the transaction response has been provided by the Context Hub,
272ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * the given listener will be invoked.
273b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     *
274ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * If the transaction has already completed at the time of invocation, the listener
275ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * will be immediately invoked. If the transaction has been invalidated,
276ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * the listener will never be invoked.
277b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     *
2786c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * A transaction can be invalidated if the process owning the transaction is no longer active
2796c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * and the reference to this object is lost.
2806c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
281b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro     * This method or {@link #setOnCompleteListener(ContextHubTransaction.OnCompleteListener)} can
282b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro     * only be invoked once, or an IllegalStateException will be thrown.
2836c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
284ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * @param listener the listener to be invoked upon completion
285e35a6debaaec952800cf74020886e6bb50618f7dArthur Ishiguro     * @param executor the executor to invoke the callback
2866c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
2876c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * @throws IllegalStateException if this method is called multiple times
2886c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * @throws NullPointerException if the callback or handler is null
289b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro     */
290ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro    public void setOnCompleteListener(
291b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro            @NonNull ContextHubTransaction.OnCompleteListener<T> listener,
292e35a6debaaec952800cf74020886e6bb50618f7dArthur Ishiguro            @NonNull @CallbackExecutor Executor executor) {
2936c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro        synchronized (this) {
294b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro            Preconditions.checkNotNull(listener, "OnCompleteListener cannot be null");
295ac7b959be1fb268a3e387b57df0ee7b1e52b7cc3Arthur Ishiguro            Preconditions.checkNotNull(executor, "Executor cannot be null");
296ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro            if (mListener != null) {
2976c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro                throw new IllegalStateException(
298ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro                        "Cannot set ContextHubTransaction listener multiple times");
2996c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            }
3006c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
301ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro            mListener = listener;
302e35a6debaaec952800cf74020886e6bb50618f7dArthur Ishiguro            mExecutor = executor;
3036c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
3046c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            if (mDoneSignal.getCount() == 0) {
305ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro                mExecutor.execute(() -> mListener.onComplete(this, mResponse));
3066c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            }
3076c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro        }
308b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    }
309b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro
3106c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    /**
311ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * Sets the listener to be invoked invoked when the transaction completes.
3126c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
313b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro     * Equivalent to {@link #setOnCompleteListener(ContextHubTransaction.OnCompleteListener,
314b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro     * Executor)} with the executor using the main thread's Looper.
3156c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
316b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro     * This method or {@link #setOnCompleteListener(ContextHubTransaction.OnCompleteListener,
317b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro     * Executor)} can only be invoked once, or an IllegalStateException will be thrown.
3186c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
319ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro     * @param listener the listener to be invoked upon completion
3206c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
3216c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * @throws IllegalStateException if this method is called multiple times
3226c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * @throws NullPointerException if the callback is null
3236c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     */
324b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro    public void setOnCompleteListener(
325b3dce5bd81fb9ba7e49bef0f6ec8bf2a6394ec4bArthur Ishiguro            @NonNull ContextHubTransaction.OnCompleteListener<T> listener) {
326ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro        setOnCompleteListener(listener, new HandlerExecutor(Handler.getMain()));
3276c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    }
3286c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
3296c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro    /**
3306c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * Sets the response of the transaction.
3316c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
3326c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * This method should only be invoked by ContextHubManager as a result of a callback from
3336c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * the Context Hub Service indicating the response from a transaction. This method should not be
3346c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * invoked more than once.
3356c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
3366c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * @param response the response to set
3376c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     *
3386c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * @throws IllegalStateException if this method is invoked multiple times
3396c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     * @throws NullPointerException if the response is null
3406c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro     */
341e35a6debaaec952800cf74020886e6bb50618f7dArthur Ishiguro    /* package */ void setResponse(ContextHubTransaction.Response<T> response) {
3426c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro        synchronized (this) {
343ac7b959be1fb268a3e387b57df0ee7b1e52b7cc3Arthur Ishiguro            Preconditions.checkNotNull(response, "Response cannot be null");
3446c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            if (mIsResponseSet) {
3456c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro                throw new IllegalStateException(
3466c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro                        "Cannot set response of ContextHubTransaction multiple times");
3476c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            }
3486c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
3496c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            mResponse = response;
3506c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            mIsResponseSet = true;
3516c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro
3526c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            mDoneSignal.countDown();
353ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro            if (mListener != null) {
354ddb737ff0fd0cd6de00e2d3761e4695bcc437e42Arthur Ishiguro                mExecutor.execute(() -> mListener.onComplete(this, mResponse));
3556c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro            }
3566c37fd0f538c4a6f40589ba1e91d95449f0b8195Arthur Ishiguro        }
357b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro    }
358b9ae7bd8389deeb4abbe034dc97f151c60c13044Arthur Ishiguro}
359