Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / cacheinvalidation / src / java / com / google / ipc / invalidation / external / client / contrib / AndroidListenerIntents.java
1 /*
2  * Copyright 2011 Google Inc.
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 package com.google.ipc.invalidation.external.client.contrib;
17
18 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
19 import com.google.ipc.invalidation.external.client.android.service.AndroidLogger;
20 import com.google.ipc.invalidation.external.client.contrib.AndroidListener.AlarmReceiver;
21 import com.google.ipc.invalidation.external.client.types.ObjectId;
22 import com.google.ipc.invalidation.ticl.android2.AndroidClock;
23 import com.google.ipc.invalidation.ticl.android2.AndroidTiclManifest;
24 import com.google.ipc.invalidation.ticl.android2.channel.AndroidChannelConstants.AuthTokenConstants;
25 import com.google.protobuf.ByteString;
26 import com.google.protobuf.InvalidProtocolBufferException;
27 import com.google.protos.ipc.invalidation.AndroidListenerProtocol.RegistrationCommand;
28 import com.google.protos.ipc.invalidation.AndroidListenerProtocol.StartCommand;
29
30 import android.app.AlarmManager;
31 import android.app.PendingIntent;
32 import android.app.PendingIntent.CanceledException;
33 import android.content.Context;
34 import android.content.Intent;
35
36
37 /**
38  * Static helper class supporting construction and decoding of intents issued and handled by the
39  * {@link AndroidListener}.
40  *
41  */
42 class AndroidListenerIntents {
43
44   /** The logger. */
45   private static final Logger logger = AndroidLogger.forPrefix("");
46
47   /** Key of Intent byte[] holding a {@link RegistrationCommand} protocol buffer. */
48   static final String EXTRA_REGISTRATION =
49       "com.google.ipc.invalidation.android_listener.REGISTRATION";
50
51   /** Key of Intent byte[] holding a {@link StartCommand} protocol buffer. */
52   static final String EXTRA_START =
53       "com.google.ipc.invalidation.android_listener.START";
54
55   /** Key of Intent extra indicating that the client should stop. */
56   static final String EXTRA_STOP =
57       "com.google.ipc.invalidation.android_listener.STOP";
58
59   /** Key of Intent extra holding a byte[] that is ack handle data. */
60   static final String EXTRA_ACK =
61       "com.google.ipc.invalidation.android_listener.ACK";
62
63   /**
64    * Issues the given {@code intent} to the TICL service class registered in the {@code context}.
65    */
66   static void issueTiclIntent(Context context, Intent intent) {
67     context.startService(intent.setClassName(context,
68         new AndroidTiclManifest(context).getTiclServiceClass()));
69   }
70
71   /**
72    * Issues the given {@code intent} to the {@link AndroidListener} class registered in the
73    * {@code context}.
74    */
75   static void issueAndroidListenerIntent(Context context, Intent intent) {
76     context.startService(setAndroidListenerClass(context, intent));
77   }
78
79   /**
80    * Returns the ack handle from the given intent if it has the appropriate extra. Otherwise,
81    * returns {@code null}.
82    */
83   static byte[] findAckHandle(Intent intent) {
84     return intent.getByteArrayExtra(EXTRA_ACK);
85   }
86
87   /**
88    * Returns {@link RegistrationCommand} extra from the given intent or null if no valid
89    * registration command exists.
90    */
91   static RegistrationCommand findRegistrationCommand(Intent intent) {
92     // Check that the extra exists.
93     byte[] data = intent.getByteArrayExtra(EXTRA_REGISTRATION);
94     if (null == data) {
95       return null;
96     }
97
98     // Attempt to parse the extra.
99     try {
100       return RegistrationCommand.parseFrom(data);
101     } catch (InvalidProtocolBufferException exception) {
102       logger.warning("Received invalid proto: %s", exception);
103       return null;
104     }
105   }
106
107   /**
108    * Returns {@link StartCommand} extra from the given intent or null if no valid start command
109    * exists.
110    */
111   static StartCommand findStartCommand(Intent intent) {
112     // Check that the extra exists.
113     byte[] data = intent.getByteArrayExtra(EXTRA_START);
114     if (null == data) {
115       return null;
116     }
117
118     // Attempt to parse the extra.
119     try {
120       return StartCommand.parseFrom(data);
121     } catch (InvalidProtocolBufferException exception) {
122       logger.warning("Received invalid proto: %s", exception);
123       return null;
124     }
125   }
126
127   /** Returns {@code true} if the intent has the 'stop' extra. */
128   static boolean isStopIntent(Intent intent) {
129     return intent.hasExtra(EXTRA_STOP);
130   }
131
132   /** Issues a registration retry with delay. */
133   static void issueDelayedRegistrationIntent(Context context, AndroidClock clock,
134       ByteString clientId, ObjectId objectId, boolean isRegister, int delayMs, int requestCode) {
135     RegistrationCommand command = isRegister ?
136         AndroidListenerProtos.newDelayedRegisterCommand(clientId, objectId) :
137             AndroidListenerProtos.newDelayedUnregisterCommand(clientId, objectId);
138     Intent intent = new Intent()
139         .putExtra(EXTRA_REGISTRATION, command.toByteArray())
140         .setClass(context, AlarmReceiver.class);
141
142     // Create a pending intent that will cause the AlarmManager to fire the above intent.
143     PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent,
144         PendingIntent.FLAG_ONE_SHOT);
145
146     // Schedule the pending intent after the appropriate delay.
147     AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
148     long executeMs = clock.nowMs() + delayMs;
149     alarmManager.set(AlarmManager.RTC, executeMs, pendingIntent);
150   }
151
152   /** Creates a 'start-client' intent. */
153   static Intent createStartIntent(Context context, int clientType, byte[] clientName,
154       boolean allowSuppression) {
155     Intent intent = new Intent();
156     // Create proto for the start command.
157     StartCommand command = AndroidListenerProtos.newStartCommand(clientType,
158         ByteString.copyFrom(clientName), allowSuppression);
159     intent.putExtra(EXTRA_START, command.toByteArray());
160     return setAndroidListenerClass(context, intent);
161   }
162
163   /** Creates a 'stop-client' intent. */
164   static Intent createStopIntent(Context context) {
165     // Stop command just has the extra (its content doesn't matter).
166     Intent intent = new Intent();
167     intent.putExtra(EXTRA_STOP, true);
168     return setAndroidListenerClass(context, intent);
169   }
170
171   /** Create an ack intent. */
172   static Intent createAckIntent(Context context, byte[] ackHandle) {
173     // Ack intent has an extra containing the ack handle data.
174     Intent intent = new Intent();
175     intent.putExtra(EXTRA_ACK, ackHandle);
176     return setAndroidListenerClass(context, intent);
177   }
178
179   /** Constructs an intent with {@link RegistrationCommand} proto. */
180   static Intent createRegistrationIntent(Context context, byte[] clientId,
181       Iterable<ObjectId> objectIds, boolean isRegister) {
182     // Registration intent has an extra containing the RegistrationCommand proto.
183     Intent intent = new Intent();
184     RegistrationCommand command = isRegister
185         ? AndroidListenerProtos.newRegisterCommand(ByteString.copyFrom(clientId), objectIds)
186             : AndroidListenerProtos.newUnregisterCommand(ByteString.copyFrom(clientId), objectIds);
187     intent.putExtra(EXTRA_REGISTRATION, command.toByteArray());
188     return setAndroidListenerClass(context, intent);
189   }
190
191   /** Sets the appropriate class for {@link AndroidListener} service intents. */
192   static Intent setAndroidListenerClass(Context context, Intent intent) {
193     String simpleListenerClass = new AndroidTiclManifest(context).getListenerServiceClass();
194     return intent.setClassName(context, simpleListenerClass);
195   }
196
197   /** Returns {@code true} iff the given intent is an authorization token request. */
198   static boolean isAuthTokenRequest(Intent intent) {
199     return AuthTokenConstants.ACTION_REQUEST_AUTH_TOKEN.equals(intent.getAction());
200   }
201
202   /**
203    * Given an authorization token request intent and authorization information ({@code authToken}
204    * and {@code authType}) issues a response.
205    */
206   static void issueAuthTokenResponse(Context context, PendingIntent pendingIntent, String authToken,
207       String authType) {
208     Intent responseIntent = new Intent()
209         .putExtra(AuthTokenConstants.EXTRA_AUTH_TOKEN, authToken)
210         .putExtra(AuthTokenConstants.EXTRA_AUTH_TOKEN_TYPE, authType);
211     try {
212       pendingIntent.send(context, 0, responseIntent);
213     } catch (CanceledException exception) {
214       logger.warning("Canceled auth request: %s", exception);
215     }
216   }
217
218   // Prevent instantiation.
219   private AndroidListenerIntents() {
220   }
221 }