Bug 793053 - Part 3: product announcements service. r=nalexander
authorRichard Newman <rnewman@mozilla.com>
Fri, 26 Oct 2012 17:37:49 -0700
changeset 111722 717cd6ee20fc14c257ef8059889a9181ca1792a2
parent 111721 eace14fccc472a3c7dc416e402fabc5447db05e0
child 111723 1330fdc14cb0bd2add8fbbb8116cdbe354b9331f
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersnalexander
bugs793053
milestone19.0a1
Bug 793053 - Part 3: product announcements service. r=nalexander
mobile/android/base/android-services-files.mk
mobile/android/base/background/BackgroundConstants.java
mobile/android/base/background/announcements/Announcement.java
mobile/android/base/background/announcements/AnnouncementPresenter.java
mobile/android/base/background/announcements/AnnouncementsBroadcastReceiver.java
mobile/android/base/background/announcements/AnnouncementsBroadcastService.java
mobile/android/base/background/announcements/AnnouncementsConstants.java
mobile/android/base/background/announcements/AnnouncementsFetchDelegate.java
mobile/android/base/background/announcements/AnnouncementsFetchResourceDelegate.java
mobile/android/base/background/announcements/AnnouncementsFetcher.java
mobile/android/base/background/announcements/AnnouncementsService.java
mobile/android/base/background/announcements/AnnouncementsStartReceiver.java
mobile/android/base/sync/net/BaseResource.java
mobile/android/services/java-sources.mn
mobile/android/services/manifests/AnnouncementsAndroidManifest_activities.xml.in
mobile/android/services/manifests/AnnouncementsAndroidManifest_permissions.xml.in
mobile/android/services/manifests/AnnouncementsAndroidManifest_services.xml.in
--- a/mobile/android/base/android-services-files.mk
+++ b/mobile/android/base/android-services-files.mk
@@ -1,14 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # These files are managed in the android-sync repo. Do not modify directly, or your changes will be lost.
-SYNC_JAVA_FILES := sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CommandProcessor.java sync/CommandRunner.java sync/config/AccountPickler.java sync/config/activities/SelectEnginesActivity.java sync/config/ClientRecordTerminator.java sync/config/ConfigurationMigrator.java sync/CredentialException.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/crypto/PersistedCrypto5Keys.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/ClientsDataDelegate.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/EngineSettings.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeJson.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/stage/CompleteStage.java sync/jpake/stage/ComputeFinalStage.java sync/jpake/stage/ComputeKeyVerificationStage.java sync/jpake/stage/ComputeStepOneStage.java sync/jpake/stage/ComputeStepTwoStage.java sync/jpake/stage/DecryptDataStage.java sync/jpake/stage/DeleteChannel.java sync/jpake/stage/GetChannelStage.java sync/jpake/stage/GetRequestStage.java sync/jpake/stage/JPakeStage.java sync/jpake/stage/PutRequestStage.java sync/jpake/stage/VerifyPairingStage.java sync/jpake/Zkp.java sync/KeyBundleProvider.java sync/log/writers/AndroidLevelCachingLogWriter.java sync/log/writers/AndroidLogWriter.java sync/log/writers/LevelFilteringLogWriter.java sync/log/writers/LogWriter.java sync/log/writers/PrintLogWriter.java sync/log/writers/SimpleTagLogWriter.java sync/log/writers/StringLogWriter.java sync/log/writers/TagLogWriter.java sync/log/writers/ThreadLocalTagLogWriter.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/middleware/MiddlewareRepositorySession.java sync/net/BaseResource.java sync/net/ConnectionMonitorThread.java sync/net/HandleProgressException.java sync/net/HttpResponseObserver.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/net/WBORequestDelegate.java sync/NoCollectionKeysSetException.java sync/NodeAuthenticationException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/NullClusterURLException.java sync/PersistedMetaGlobal.java sync/PrefsSource.java sync/receivers/SyncAccountDeletedReceiver.java sync/receivers/SyncAccountDeletedService.java sync/receivers/UpgradeReceiver.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BookmarksDeletionManager.java sync/repositories/android/BookmarksInsertionManager.java sync/repositories/android/BrowserContractHelpers.java sync/repositories/android/CachedSQLiteOpenHelper.java sync/repositories/android/ClientsDatabase.java sync/repositories/android/ClientsDatabaseAccessor.java sync/repositories/android/FennecControlHelper.java sync/repositories/android/FennecTabsRepository.java sync/repositories/android/FormHistoryRepositorySession.java sync/repositories/android/PasswordsRepositorySession.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/ClientRecord.java sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/FormHistoryRecord.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.java sync/repositories/domain/VersionConstants.java sync/repositories/FetchFailedException.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoContentProviderException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreFailedException.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/Server11PreviousPostFailedException.java sync/Server11RecordPostFailedException.java sync/setup/activities/AccountActivity.java sync/setup/activities/ActivityUtils.java sync/setup/activities/ClientRecordArrayAdapter.java sync/setup/activities/RedirectToSetupActivity.java sync/setup/activities/SendTabActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/activities/SyncActivity.java sync/setup/activities/WebViewActivity.java sync/setup/auth/AccountAuthenticator.java sync/setup/auth/AuthenticateAccountStage.java sync/setup/auth/AuthenticationResult.java sync/setup/auth/AuthenticatorStage.java sync/setup/auth/EnsureUserExistenceStage.java sync/setup/auth/FetchUserNodeStage.java sync/setup/Constants.java sync/setup/InvalidSyncKeyException.java sync/setup/SyncAccounts.java sync/setup/SyncAuthenticatorService.java sync/stage/AbstractNonRepositorySyncStage.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureCrypto5KeysStage.java sync/stage/FennecTabsServerSyncStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/FormHistoryServerSyncStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/PasswordsServerSyncStage.java sync/stage/ServerSyncStage.java sync/stage/SyncClientsEngineStage.java sync/stage/UploadMetaGlobalStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/ServerLocalSynchronizer.java sync/synchronizer/ServerLocalSynchronizerSession.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java
+SYNC_JAVA_FILES := background/announcements/Announcement.java background/announcements/AnnouncementPresenter.java background/announcements/AnnouncementsBroadcastReceiver.java background/announcements/AnnouncementsBroadcastService.java background/announcements/AnnouncementsConstants.java background/announcements/AnnouncementsFetchDelegate.java background/announcements/AnnouncementsFetcher.java background/announcements/AnnouncementsFetchResourceDelegate.java background/announcements/AnnouncementsService.java background/announcements/AnnouncementsStartReceiver.java background/BackgroundConstants.java sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CommandProcessor.java sync/CommandRunner.java sync/config/AccountPickler.java sync/config/activities/SelectEnginesActivity.java sync/config/ClientRecordTerminator.java sync/config/ConfigurationMigrator.java sync/CredentialException.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/crypto/PersistedCrypto5Keys.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/ClientsDataDelegate.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/EngineSettings.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeJson.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/stage/CompleteStage.java sync/jpake/stage/ComputeFinalStage.java sync/jpake/stage/ComputeKeyVerificationStage.java sync/jpake/stage/ComputeStepOneStage.java sync/jpake/stage/ComputeStepTwoStage.java sync/jpake/stage/DecryptDataStage.java sync/jpake/stage/DeleteChannel.java sync/jpake/stage/GetChannelStage.java sync/jpake/stage/GetRequestStage.java sync/jpake/stage/JPakeStage.java sync/jpake/stage/PutRequestStage.java sync/jpake/stage/VerifyPairingStage.java sync/jpake/Zkp.java sync/KeyBundleProvider.java sync/log/writers/AndroidLevelCachingLogWriter.java sync/log/writers/AndroidLogWriter.java sync/log/writers/LevelFilteringLogWriter.java sync/log/writers/LogWriter.java sync/log/writers/PrintLogWriter.java sync/log/writers/SimpleTagLogWriter.java sync/log/writers/StringLogWriter.java sync/log/writers/TagLogWriter.java sync/log/writers/ThreadLocalTagLogWriter.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/middleware/MiddlewareRepositorySession.java sync/net/BaseResource.java sync/net/ConnectionMonitorThread.java sync/net/HandleProgressException.java sync/net/HttpResponseObserver.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/net/WBORequestDelegate.java sync/NoCollectionKeysSetException.java sync/NodeAuthenticationException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/NullClusterURLException.java sync/PersistedMetaGlobal.java sync/PrefsSource.java sync/receivers/SyncAccountDeletedReceiver.java sync/receivers/SyncAccountDeletedService.java sync/receivers/UpgradeReceiver.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BookmarksDeletionManager.java sync/repositories/android/BookmarksInsertionManager.java sync/repositories/android/BrowserContractHelpers.java sync/repositories/android/CachedSQLiteOpenHelper.java sync/repositories/android/ClientsDatabase.java sync/repositories/android/ClientsDatabaseAccessor.java sync/repositories/android/FennecControlHelper.java sync/repositories/android/FennecTabsRepository.java sync/repositories/android/FormHistoryRepositorySession.java sync/repositories/android/PasswordsRepositorySession.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/ClientRecord.java sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/FormHistoryRecord.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.java sync/repositories/domain/VersionConstants.java sync/repositories/FetchFailedException.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoContentProviderException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreFailedException.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/Server11PreviousPostFailedException.java sync/Server11RecordPostFailedException.java sync/setup/activities/AccountActivity.java sync/setup/activities/ActivityUtils.java sync/setup/activities/ClientRecordArrayAdapter.java sync/setup/activities/RedirectToSetupActivity.java sync/setup/activities/SendTabActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/activities/SyncActivity.java sync/setup/activities/WebViewActivity.java sync/setup/auth/AccountAuthenticator.java sync/setup/auth/AuthenticateAccountStage.java sync/setup/auth/AuthenticationResult.java sync/setup/auth/AuthenticatorStage.java sync/setup/auth/EnsureUserExistenceStage.java sync/setup/auth/FetchUserNodeStage.java sync/setup/Constants.java sync/setup/InvalidSyncKeyException.java sync/setup/SyncAccounts.java sync/setup/SyncAuthenticatorService.java sync/stage/AbstractNonRepositorySyncStage.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureCrypto5KeysStage.java sync/stage/FennecTabsServerSyncStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/FormHistoryServerSyncStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/PasswordsServerSyncStage.java sync/stage/ServerSyncStage.java sync/stage/SyncClientsEngineStage.java sync/stage/UploadMetaGlobalStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/ServerLocalSynchronizer.java sync/synchronizer/ServerLocalSynchronizerSession.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java
 SYNC_PP_JAVA_FILES := sync/GlobalConstants.java sync/SyncConstants.java
 SYNC_THIRDPARTY_JAVA_FILES := httpclientandroidlib/androidextra/HttpClientAndroidLog.java httpclientandroidlib/annotation/GuardedBy.java httpclientandroidlib/annotation/Immutable.java httpclientandroidlib/annotation/NotThreadSafe.java httpclientandroidlib/annotation/ThreadSafe.java httpclientandroidlib/auth/AUTH.java httpclientandroidlib/auth/AuthenticationException.java httpclientandroidlib/auth/AuthScheme.java httpclientandroidlib/auth/AuthSchemeFactory.java httpclientandroidlib/auth/AuthSchemeRegistry.java httpclientandroidlib/auth/AuthScope.java httpclientandroidlib/auth/AuthState.java httpclientandroidlib/auth/BasicUserPrincipal.java httpclientandroidlib/auth/ContextAwareAuthScheme.java httpclientandroidlib/auth/Credentials.java httpclientandroidlib/auth/InvalidCredentialsException.java httpclientandroidlib/auth/MalformedChallengeException.java httpclientandroidlib/auth/NTCredentials.java httpclientandroidlib/auth/NTUserPrincipal.java httpclientandroidlib/auth/params/AuthParamBean.java httpclientandroidlib/auth/params/AuthParams.java httpclientandroidlib/auth/params/AuthPNames.java httpclientandroidlib/auth/UsernamePasswordCredentials.java httpclientandroidlib/client/AuthCache.java httpclientandroidlib/client/AuthenticationHandler.java httpclientandroidlib/client/CircularRedirectException.java httpclientandroidlib/client/ClientProtocolException.java httpclientandroidlib/client/CookieStore.java httpclientandroidlib/client/CredentialsProvider.java httpclientandroidlib/client/entity/DecompressingEntity.java httpclientandroidlib/client/entity/DeflateDecompressingEntity.java httpclientandroidlib/client/entity/GzipDecompressingEntity.java httpclientandroidlib/client/entity/UrlEncodedFormEntity.java httpclientandroidlib/client/HttpClient.java httpclientandroidlib/client/HttpRequestRetryHandler.java httpclientandroidlib/client/HttpResponseException.java httpclientandroidlib/client/methods/AbortableHttpRequest.java httpclientandroidlib/client/methods/HttpDelete.java httpclientandroidlib/client/methods/HttpEntityEnclosingRequestBase.java httpclientandroidlib/client/methods/HttpGet.java httpclientandroidlib/client/methods/HttpHead.java httpclientandroidlib/client/methods/HttpOptions.java httpclientandroidlib/client/methods/HttpPost.java httpclientandroidlib/client/methods/HttpPut.java httpclientandroidlib/client/methods/HttpRequestBase.java httpclientandroidlib/client/methods/HttpTrace.java httpclientandroidlib/client/methods/HttpUriRequest.java httpclientandroidlib/client/NonRepeatableRequestException.java httpclientandroidlib/client/params/AllClientPNames.java httpclientandroidlib/client/params/AuthPolicy.java httpclientandroidlib/client/params/ClientParamBean.java httpclientandroidlib/client/params/ClientPNames.java httpclientandroidlib/client/params/CookiePolicy.java httpclientandroidlib/client/params/HttpClientParams.java httpclientandroidlib/client/protocol/ClientContext.java httpclientandroidlib/client/protocol/ClientContextConfigurer.java httpclientandroidlib/client/protocol/RequestAcceptEncoding.java httpclientandroidlib/client/protocol/RequestAddCookies.java httpclientandroidlib/client/protocol/RequestAuthCache.java httpclientandroidlib/client/protocol/RequestClientConnControl.java httpclientandroidlib/client/protocol/RequestDefaultHeaders.java httpclientandroidlib/client/protocol/RequestProxyAuthentication.java httpclientandroidlib/client/protocol/RequestTargetAuthentication.java httpclientandroidlib/client/protocol/ResponseAuthCache.java httpclientandroidlib/client/protocol/ResponseContentEncoding.java httpclientandroidlib/client/protocol/ResponseProcessCookies.java httpclientandroidlib/client/RedirectException.java httpclientandroidlib/client/RedirectHandler.java httpclientandroidlib/client/RedirectStrategy.java httpclientandroidlib/client/RequestDirector.java httpclientandroidlib/client/ResponseHandler.java httpclientandroidlib/client/UserTokenHandler.java httpclientandroidlib/client/utils/CloneUtils.java httpclientandroidlib/client/utils/Idn.java httpclientandroidlib/client/utils/JdkIdn.java httpclientandroidlib/client/utils/Punycode.java httpclientandroidlib/client/utils/Rfc3492Idn.java httpclientandroidlib/client/utils/URIUtils.java httpclientandroidlib/client/utils/URLEncodedUtils.java httpclientandroidlib/conn/BasicEofSensorWatcher.java httpclientandroidlib/conn/BasicManagedEntity.java httpclientandroidlib/conn/ClientConnectionManager.java httpclientandroidlib/conn/ClientConnectionManagerFactory.java httpclientandroidlib/conn/ClientConnectionOperator.java httpclientandroidlib/conn/ClientConnectionRequest.java httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java httpclientandroidlib/conn/ConnectionPoolTimeoutException.java httpclientandroidlib/conn/ConnectionReleaseTrigger.java httpclientandroidlib/conn/ConnectTimeoutException.java httpclientandroidlib/conn/EofSensorInputStream.java httpclientandroidlib/conn/EofSensorWatcher.java httpclientandroidlib/conn/HttpHostConnectException.java httpclientandroidlib/conn/HttpRoutedConnection.java httpclientandroidlib/conn/ManagedClientConnection.java httpclientandroidlib/conn/MultihomePlainSocketFactory.java httpclientandroidlib/conn/OperatedClientConnection.java httpclientandroidlib/conn/params/ConnConnectionParamBean.java httpclientandroidlib/conn/params/ConnConnectionPNames.java httpclientandroidlib/conn/params/ConnManagerParamBean.java httpclientandroidlib/conn/params/ConnManagerParams.java httpclientandroidlib/conn/params/ConnManagerPNames.java httpclientandroidlib/conn/params/ConnPerRoute.java httpclientandroidlib/conn/params/ConnPerRouteBean.java httpclientandroidlib/conn/params/ConnRouteParamBean.java httpclientandroidlib/conn/params/ConnRouteParams.java httpclientandroidlib/conn/params/ConnRoutePNames.java httpclientandroidlib/conn/routing/BasicRouteDirector.java httpclientandroidlib/conn/routing/HttpRoute.java httpclientandroidlib/conn/routing/HttpRouteDirector.java httpclientandroidlib/conn/routing/HttpRoutePlanner.java httpclientandroidlib/conn/routing/RouteInfo.java httpclientandroidlib/conn/routing/RouteTracker.java httpclientandroidlib/conn/scheme/HostNameResolver.java httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactoryAdaptor.java httpclientandroidlib/conn/scheme/LayeredSocketFactory.java httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java httpclientandroidlib/conn/scheme/PlainSocketFactory.java httpclientandroidlib/conn/scheme/Scheme.java httpclientandroidlib/conn/scheme/SchemeRegistry.java httpclientandroidlib/conn/scheme/SchemeSocketFactory.java httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java httpclientandroidlib/conn/scheme/SocketFactory.java httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java httpclientandroidlib/conn/ssl/AbstractVerifier.java httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java httpclientandroidlib/conn/ssl/SSLSocketFactory.java httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java httpclientandroidlib/conn/ssl/TrustManagerDecorator.java httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java httpclientandroidlib/conn/ssl/TrustStrategy.java httpclientandroidlib/conn/ssl/X509HostnameVerifier.java httpclientandroidlib/conn/util/InetAddressUtils.java httpclientandroidlib/ConnectionClosedException.java httpclientandroidlib/ConnectionReuseStrategy.java httpclientandroidlib/cookie/ClientCookie.java httpclientandroidlib/cookie/Cookie.java httpclientandroidlib/cookie/CookieAttributeHandler.java httpclientandroidlib/cookie/CookieIdentityComparator.java httpclientandroidlib/cookie/CookieOrigin.java httpclientandroidlib/cookie/CookiePathComparator.java httpclientandroidlib/cookie/CookieRestrictionViolationException.java httpclientandroidlib/cookie/CookieSpec.java httpclientandroidlib/cookie/CookieSpecFactory.java httpclientandroidlib/cookie/CookieSpecRegistry.java httpclientandroidlib/cookie/MalformedCookieException.java httpclientandroidlib/cookie/params/CookieSpecParamBean.java httpclientandroidlib/cookie/params/CookieSpecPNames.java httpclientandroidlib/cookie/SetCookie.java httpclientandroidlib/cookie/SetCookie2.java httpclientandroidlib/cookie/SM.java httpclientandroidlib/entity/AbstractHttpEntity.java httpclientandroidlib/entity/BasicHttpEntity.java httpclientandroidlib/entity/BufferedHttpEntity.java httpclientandroidlib/entity/ByteArrayEntity.java httpclientandroidlib/entity/ContentLengthStrategy.java httpclientandroidlib/entity/ContentProducer.java httpclientandroidlib/entity/EntityTemplate.java httpclientandroidlib/entity/FileEntity.java httpclientandroidlib/entity/HttpEntityWrapper.java httpclientandroidlib/entity/InputStreamEntity.java httpclientandroidlib/entity/SerializableEntity.java httpclientandroidlib/entity/StringEntity.java httpclientandroidlib/FormattedHeader.java httpclientandroidlib/Header.java httpclientandroidlib/HeaderElement.java httpclientandroidlib/HeaderElementIterator.java httpclientandroidlib/HeaderIterator.java httpclientandroidlib/HttpClientConnection.java httpclientandroidlib/HttpConnection.java httpclientandroidlib/HttpConnectionMetrics.java httpclientandroidlib/HttpEntity.java httpclientandroidlib/HttpEntityEnclosingRequest.java httpclientandroidlib/HttpException.java httpclientandroidlib/HttpHeaders.java httpclientandroidlib/HttpHost.java httpclientandroidlib/HttpInetConnection.java httpclientandroidlib/HttpMessage.java httpclientandroidlib/HttpRequest.java httpclientandroidlib/HttpRequestFactory.java httpclientandroidlib/HttpRequestInterceptor.java httpclientandroidlib/HttpResponse.java httpclientandroidlib/HttpResponseFactory.java httpclientandroidlib/HttpResponseInterceptor.java httpclientandroidlib/HttpServerConnection.java httpclientandroidlib/HttpStatus.java httpclientandroidlib/HttpVersion.java httpclientandroidlib/impl/AbstractHttpClientConnection.java httpclientandroidlib/impl/AbstractHttpServerConnection.java httpclientandroidlib/impl/auth/AuthSchemeBase.java httpclientandroidlib/impl/auth/BasicScheme.java httpclientandroidlib/impl/auth/BasicSchemeFactory.java httpclientandroidlib/impl/auth/DigestScheme.java httpclientandroidlib/impl/auth/DigestSchemeFactory.java httpclientandroidlib/impl/auth/NTLMEngine.java httpclientandroidlib/impl/auth/NTLMEngineException.java httpclientandroidlib/impl/auth/NTLMEngineImpl.java httpclientandroidlib/impl/auth/NTLMScheme.java httpclientandroidlib/impl/auth/NTLMSchemeFactory.java httpclientandroidlib/impl/auth/RFC2617Scheme.java httpclientandroidlib/impl/auth/SpnegoTokenGenerator.java httpclientandroidlib/impl/auth/UnsupportedDigestAlgorithmException.java httpclientandroidlib/impl/client/AbstractAuthenticationHandler.java httpclientandroidlib/impl/client/AbstractHttpClient.java httpclientandroidlib/impl/client/BasicAuthCache.java httpclientandroidlib/impl/client/BasicCookieStore.java httpclientandroidlib/impl/client/BasicCredentialsProvider.java httpclientandroidlib/impl/client/BasicResponseHandler.java httpclientandroidlib/impl/client/ClientParamsStack.java httpclientandroidlib/impl/client/ContentEncodingHttpClient.java httpclientandroidlib/impl/client/DefaultConnectionKeepAliveStrategy.java httpclientandroidlib/impl/client/DefaultHttpClient.java httpclientandroidlib/impl/client/DefaultHttpRequestRetryHandler.java httpclientandroidlib/impl/client/DefaultProxyAuthenticationHandler.java httpclientandroidlib/impl/client/DefaultRedirectHandler.java httpclientandroidlib/impl/client/DefaultRedirectStrategy.java httpclientandroidlib/impl/client/DefaultRedirectStrategyAdaptor.java httpclientandroidlib/impl/client/DefaultRequestDirector.java httpclientandroidlib/impl/client/DefaultTargetAuthenticationHandler.java httpclientandroidlib/impl/client/DefaultUserTokenHandler.java httpclientandroidlib/impl/client/EntityEnclosingRequestWrapper.java httpclientandroidlib/impl/client/RedirectLocations.java httpclientandroidlib/impl/client/RequestWrapper.java httpclientandroidlib/impl/client/RoutedRequest.java httpclientandroidlib/impl/client/TunnelRefusedException.java httpclientandroidlib/impl/conn/AbstractClientConnAdapter.java httpclientandroidlib/impl/conn/AbstractPooledConnAdapter.java httpclientandroidlib/impl/conn/AbstractPoolEntry.java httpclientandroidlib/impl/conn/ConnectionShutdownException.java httpclientandroidlib/impl/conn/DefaultClientConnection.java httpclientandroidlib/impl/conn/DefaultClientConnectionOperator.java httpclientandroidlib/impl/conn/DefaultHttpRoutePlanner.java httpclientandroidlib/impl/conn/DefaultResponseParser.java httpclientandroidlib/impl/conn/HttpInetSocketAddress.java httpclientandroidlib/impl/conn/IdleConnectionHandler.java httpclientandroidlib/impl/conn/LoggingSessionInputBuffer.java httpclientandroidlib/impl/conn/LoggingSessionOutputBuffer.java httpclientandroidlib/impl/conn/ProxySelectorRoutePlanner.java httpclientandroidlib/impl/conn/SchemeRegistryFactory.java httpclientandroidlib/impl/conn/SingleClientConnManager.java httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java httpclientandroidlib/impl/conn/tsccm/BasicPooledConnAdapter.java httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java httpclientandroidlib/impl/conn/tsccm/RefQueueHandler.java httpclientandroidlib/impl/conn/tsccm/RefQueueWorker.java httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java httpclientandroidlib/impl/conn/tsccm/WaitingThread.java httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java httpclientandroidlib/impl/conn/Wire.java httpclientandroidlib/impl/cookie/AbstractCookieAttributeHandler.java httpclientandroidlib/impl/cookie/AbstractCookieSpec.java httpclientandroidlib/impl/cookie/BasicClientCookie.java httpclientandroidlib/impl/cookie/BasicClientCookie2.java httpclientandroidlib/impl/cookie/BasicCommentHandler.java httpclientandroidlib/impl/cookie/BasicDomainHandler.java httpclientandroidlib/impl/cookie/BasicExpiresHandler.java httpclientandroidlib/impl/cookie/BasicMaxAgeHandler.java httpclientandroidlib/impl/cookie/BasicPathHandler.java httpclientandroidlib/impl/cookie/BasicSecureHandler.java httpclientandroidlib/impl/cookie/BestMatchSpec.java httpclientandroidlib/impl/cookie/BestMatchSpecFactory.java httpclientandroidlib/impl/cookie/BrowserCompatSpec.java httpclientandroidlib/impl/cookie/BrowserCompatSpecFactory.java httpclientandroidlib/impl/cookie/CookieSpecBase.java httpclientandroidlib/impl/cookie/DateParseException.java httpclientandroidlib/impl/cookie/DateUtils.java httpclientandroidlib/impl/cookie/IgnoreSpec.java httpclientandroidlib/impl/cookie/IgnoreSpecFactory.java httpclientandroidlib/impl/cookie/NetscapeDomainHandler.java httpclientandroidlib/impl/cookie/NetscapeDraftHeaderParser.java httpclientandroidlib/impl/cookie/NetscapeDraftSpec.java httpclientandroidlib/impl/cookie/NetscapeDraftSpecFactory.java httpclientandroidlib/impl/cookie/PublicSuffixFilter.java httpclientandroidlib/impl/cookie/PublicSuffixListParser.java httpclientandroidlib/impl/cookie/RFC2109DomainHandler.java httpclientandroidlib/impl/cookie/RFC2109Spec.java httpclientandroidlib/impl/cookie/RFC2109SpecFactory.java httpclientandroidlib/impl/cookie/RFC2109VersionHandler.java httpclientandroidlib/impl/cookie/RFC2965CommentUrlAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965DiscardAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965DomainAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965PortAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965Spec.java httpclientandroidlib/impl/cookie/RFC2965SpecFactory.java httpclientandroidlib/impl/cookie/RFC2965VersionAttributeHandler.java httpclientandroidlib/impl/DefaultConnectionReuseStrategy.java httpclientandroidlib/impl/DefaultHttpClientConnection.java httpclientandroidlib/impl/DefaultHttpRequestFactory.java httpclientandroidlib/impl/DefaultHttpResponseFactory.java httpclientandroidlib/impl/DefaultHttpServerConnection.java httpclientandroidlib/impl/EnglishReasonPhraseCatalog.java httpclientandroidlib/impl/entity/EntityDeserializer.java httpclientandroidlib/impl/entity/EntitySerializer.java httpclientandroidlib/impl/entity/LaxContentLengthStrategy.java httpclientandroidlib/impl/entity/StrictContentLengthStrategy.java httpclientandroidlib/impl/HttpConnectionMetricsImpl.java httpclientandroidlib/impl/io/AbstractMessageParser.java httpclientandroidlib/impl/io/AbstractMessageWriter.java httpclientandroidlib/impl/io/AbstractSessionInputBuffer.java httpclientandroidlib/impl/io/AbstractSessionOutputBuffer.java httpclientandroidlib/impl/io/ChunkedInputStream.java httpclientandroidlib/impl/io/ChunkedOutputStream.java httpclientandroidlib/impl/io/ContentLengthInputStream.java httpclientandroidlib/impl/io/ContentLengthOutputStream.java httpclientandroidlib/impl/io/HttpRequestParser.java httpclientandroidlib/impl/io/HttpRequestWriter.java httpclientandroidlib/impl/io/HttpResponseParser.java httpclientandroidlib/impl/io/HttpResponseWriter.java httpclientandroidlib/impl/io/HttpTransportMetricsImpl.java httpclientandroidlib/impl/io/IdentityInputStream.java httpclientandroidlib/impl/io/IdentityOutputStream.java httpclientandroidlib/impl/io/SocketInputBuffer.java httpclientandroidlib/impl/io/SocketOutputBuffer.java httpclientandroidlib/impl/NoConnectionReuseStrategy.java httpclientandroidlib/impl/SocketHttpClientConnection.java httpclientandroidlib/impl/SocketHttpServerConnection.java httpclientandroidlib/io/BufferInfo.java httpclientandroidlib/io/EofSensor.java httpclientandroidlib/io/HttpMessageParser.java httpclientandroidlib/io/HttpMessageWriter.java httpclientandroidlib/io/HttpTransportMetrics.java httpclientandroidlib/io/SessionInputBuffer.java httpclientandroidlib/io/SessionOutputBuffer.java httpclientandroidlib/MalformedChunkCodingException.java httpclientandroidlib/message/AbstractHttpMessage.java httpclientandroidlib/message/BasicHeader.java httpclientandroidlib/message/BasicHeaderElement.java httpclientandroidlib/message/BasicHeaderElementIterator.java httpclientandroidlib/message/BasicHeaderIterator.java httpclientandroidlib/message/BasicHeaderValueFormatter.java httpclientandroidlib/message/BasicHeaderValueParser.java httpclientandroidlib/message/BasicHttpEntityEnclosingRequest.java httpclientandroidlib/message/BasicHttpRequest.java httpclientandroidlib/message/BasicHttpResponse.java httpclientandroidlib/message/BasicLineFormatter.java httpclientandroidlib/message/BasicLineParser.java httpclientandroidlib/message/BasicListHeaderIterator.java httpclientandroidlib/message/BasicNameValuePair.java httpclientandroidlib/message/BasicRequestLine.java httpclientandroidlib/message/BasicStatusLine.java httpclientandroidlib/message/BasicTokenIterator.java httpclientandroidlib/message/BufferedHeader.java httpclientandroidlib/message/HeaderGroup.java httpclientandroidlib/message/HeaderValueFormatter.java httpclientandroidlib/message/HeaderValueParser.java httpclientandroidlib/message/LineFormatter.java httpclientandroidlib/message/LineParser.java httpclientandroidlib/message/ParserCursor.java httpclientandroidlib/MethodNotSupportedException.java httpclientandroidlib/NameValuePair.java httpclientandroidlib/NoHttpResponseException.java httpclientandroidlib/params/AbstractHttpParams.java httpclientandroidlib/params/BasicHttpParams.java httpclientandroidlib/params/CoreConnectionPNames.java httpclientandroidlib/params/CoreProtocolPNames.java httpclientandroidlib/params/DefaultedHttpParams.java httpclientandroidlib/params/HttpAbstractParamBean.java httpclientandroidlib/params/HttpConnectionParamBean.java httpclientandroidlib/params/HttpConnectionParams.java httpclientandroidlib/params/HttpParams.java httpclientandroidlib/params/HttpProtocolParamBean.java httpclientandroidlib/params/HttpProtocolParams.java httpclientandroidlib/params/SyncBasicHttpParams.java httpclientandroidlib/ParseException.java httpclientandroidlib/protocol/BasicHttpContext.java httpclientandroidlib/protocol/BasicHttpProcessor.java httpclientandroidlib/protocol/DefaultedHttpContext.java httpclientandroidlib/protocol/ExecutionContext.java httpclientandroidlib/protocol/HTTP.java httpclientandroidlib/protocol/HttpContext.java httpclientandroidlib/protocol/HttpDateGenerator.java httpclientandroidlib/protocol/HttpExpectationVerifier.java httpclientandroidlib/protocol/HttpProcessor.java httpclientandroidlib/protocol/HttpRequestExecutor.java httpclientandroidlib/protocol/HttpRequestHandler.java httpclientandroidlib/protocol/HttpRequestHandlerRegistry.java httpclientandroidlib/protocol/HttpRequestHandlerResolver.java httpclientandroidlib/protocol/HttpRequestInterceptorList.java httpclientandroidlib/protocol/HttpResponseInterceptorList.java httpclientandroidlib/protocol/HttpService.java httpclientandroidlib/protocol/ImmutableHttpProcessor.java httpclientandroidlib/protocol/RequestConnControl.java httpclientandroidlib/protocol/RequestContent.java httpclientandroidlib/protocol/RequestDate.java httpclientandroidlib/protocol/RequestExpectContinue.java httpclientandroidlib/protocol/RequestTargetHost.java httpclientandroidlib/protocol/RequestUserAgent.java httpclientandroidlib/protocol/ResponseConnControl.java httpclientandroidlib/protocol/ResponseContent.java httpclientandroidlib/protocol/ResponseDate.java httpclientandroidlib/protocol/ResponseServer.java httpclientandroidlib/protocol/SyncBasicHttpContext.java httpclientandroidlib/protocol/UriPatternMatcher.java httpclientandroidlib/ProtocolException.java httpclientandroidlib/ProtocolVersion.java httpclientandroidlib/ReasonPhraseCatalog.java httpclientandroidlib/RequestLine.java httpclientandroidlib/StatusLine.java httpclientandroidlib/TokenIterator.java httpclientandroidlib/TruncatedChunkException.java httpclientandroidlib/UnsupportedHttpVersionException.java httpclientandroidlib/util/ByteArrayBuffer.java httpclientandroidlib/util/CharArrayBuffer.java httpclientandroidlib/util/EncodingUtils.java httpclientandroidlib/util/EntityUtils.java httpclientandroidlib/util/ExceptionUtils.java httpclientandroidlib/util/LangUtils.java httpclientandroidlib/util/VersionInfo.java json-simple/ItemList.java json-simple/JSONArray.java json-simple/JSONAware.java json-simple/JSONObject.java json-simple/JSONStreamAware.java json-simple/JSONValue.java json-simple/parser/ContainerFactory.java json-simple/parser/ContentHandler.java json-simple/parser/JSONParser.java json-simple/parser/ParseException.java json-simple/parser/Yylex.java json-simple/parser/Yytoken.java apache/commons/codec/binary/Base32.java apache/commons/codec/binary/Base32InputStream.java apache/commons/codec/binary/Base32OutputStream.java apache/commons/codec/binary/Base64.java apache/commons/codec/binary/Base64InputStream.java apache/commons/codec/binary/Base64OutputStream.java apache/commons/codec/binary/BaseNCodec.java apache/commons/codec/binary/BaseNCodecInputStream.java apache/commons/codec/binary/BaseNCodecOutputStream.java apache/commons/codec/binary/BinaryCodec.java apache/commons/codec/binary/Hex.java apache/commons/codec/binary/StringUtils.java apache/commons/codec/BinaryDecoder.java apache/commons/codec/BinaryEncoder.java apache/commons/codec/CharEncoding.java apache/commons/codec/Decoder.java apache/commons/codec/DecoderException.java apache/commons/codec/digest/DigestUtils.java apache/commons/codec/Encoder.java apache/commons/codec/EncoderException.java apache/commons/codec/language/AbstractCaverphone.java apache/commons/codec/language/Caverphone.java apache/commons/codec/language/Caverphone1.java apache/commons/codec/language/Caverphone2.java apache/commons/codec/language/ColognePhonetic.java apache/commons/codec/language/DoubleMetaphone.java apache/commons/codec/language/Metaphone.java apache/commons/codec/language/RefinedSoundex.java apache/commons/codec/language/Soundex.java apache/commons/codec/language/SoundexUtils.java apache/commons/codec/net/BCodec.java apache/commons/codec/net/QCodec.java apache/commons/codec/net/QuotedPrintableCodec.java apache/commons/codec/net/RFC1522Codec.java apache/commons/codec/net/URLCodec.java apache/commons/codec/net/Utils.java apache/commons/codec/StringDecoder.java apache/commons/codec/StringEncoder.java apache/commons/codec/StringEncoderComparator.java
 SYNC_RES_DRAWABLE := mobile/android/base/resources/drawable/desktop.png mobile/android/base/resources/drawable/mobile.png mobile/android/base/resources/drawable/pin_background.xml
 SYNC_RES_DRAWABLE_LDPI := 
 SYNC_RES_DRAWABLE_MDPI := 
 SYNC_RES_DRAWABLE_HDPI := 
 SYNC_RES_LAYOUT := res/layout/sync_account.xml res/layout/sync_list_item.xml res/layout/sync_redirect_to_setup.xml res/layout/sync_send_tab.xml res/layout/sync_setup.xml res/layout/sync_setup_failure.xml res/layout/sync_setup_jpake_waiting.xml res/layout/sync_setup_nointernet.xml res/layout/sync_setup_pair.xml res/layout/sync_setup_success.xml res/layout/sync_setup_webview.xml
 SYNC_RES_VALUES := res/values/sync_styles.xml
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/BackgroundConstants.java
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background;
+
+/**
+ * Constants that are not specific to any individual background service.
+ */
+public class BackgroundConstants {
+
+  public static final int SHARED_PREFERENCES_MODE = 0;
+  // These are used to ask Fennec (via reflection) to send
+  // us a pref notification. This avoids us having to guess
+  // Fennec's prefs branch and pref name.
+  // Eventually Fennec might listen to startup notifications and
+  // do this automatically, but this will do for now. See Bug 800244.
+  public static String GECKO_PREFERENCES_CLASS = "org.mozilla.gecko.GeckoPreferences";
+  public static String GECKO_BROADCAST_METHOD  = "broadcastAnnouncementsPref";
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/Announcement.java
@@ -0,0 +1,111 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.mozilla.gecko.sync.ExtendedJSONObject;
+import org.mozilla.gecko.sync.Logger;
+
+/**
+ * Represents a retrieved product announcement.
+ *
+ * Instances of this class are immutable.
+ */
+public class Announcement {
+  private static final String LOG_TAG   = "Announcement";
+
+  private static final String KEY_ID    = "id";
+  private static final String KEY_TITLE = "title";
+  private static final String KEY_URL   = "url";
+  private static final String KEY_TEXT  = "text";
+
+  private final int id;
+  private final String title;
+  private final URI uri;
+  private final String text;
+
+  public Announcement(int id, String title, String text, URI uri) {
+    this.id    = id;
+    this.title = title;
+    this.uri   = uri;
+    this.text  = text;
+  }
+
+  public static Announcement parseAnnouncement(ExtendedJSONObject body) throws URISyntaxException, IllegalArgumentException {
+    final Integer id = body.getIntegerSafely(KEY_ID);
+    if (id == null) {
+      throw new IllegalArgumentException("No id provided in JSON.");
+    }
+    final String title = body.getString(KEY_TITLE);
+    if (title == null || title.trim().length() == 0) {
+      throw new IllegalArgumentException("Missing or empty announcement title.");
+    }
+    final String uri = body.getString(KEY_URL);
+    if (uri == null) {
+      // Empty or otherwise unhappy URI will throw a URISyntaxException.
+      throw new IllegalArgumentException("Missing announcement URI.");
+    }
+
+    final String text = body.getString(KEY_TEXT);
+    if (text == null) {
+      throw new IllegalArgumentException("Missing announcement body.");
+    }
+
+    return new Announcement(id, title, text, new URI(uri));
+  }
+
+  public int getId() {
+    return id;
+  }
+
+  public String getTitle() {
+    return title;
+  }
+
+  public String getText() {
+    return text;
+  }
+
+  public URI getUri() {
+    return uri;
+  }
+
+  public ExtendedJSONObject asJSON() {
+    ExtendedJSONObject out = new ExtendedJSONObject();
+    out.put(KEY_ID,    id);
+    out.put(KEY_TITLE, title);
+    out.put(KEY_URL,   uri.toASCIIString());
+    out.put(KEY_TEXT,  text);
+    return out;
+  }
+
+  /**
+   * Return false if the provided Announcement is in some way invalid,
+   * regardless of being well-formed.
+   */
+  public static boolean isValidAnnouncement(final Announcement an) {
+    final URI uri = an.getUri();
+    if (uri == null) {
+      Logger.warn(LOG_TAG, "No URI: announcement not valid.");
+      return false;
+    }
+
+    final String scheme = uri.getScheme();
+    if (scheme == null) {
+      Logger.warn(LOG_TAG, "Null scheme: announcement not valid.");
+      return false;
+    }
+
+    // Only allow HTTP and HTTPS URLs.
+    if (!scheme.equalsIgnoreCase("http") && !scheme.equalsIgnoreCase("https")) {
+      Logger.warn(LOG_TAG, "Scheme '" + scheme + "' forbidden: announcement not valid.");
+      return false;
+    }
+
+    return true;
+  }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/AnnouncementPresenter.java
@@ -0,0 +1,82 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import java.net.URI;
+
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.sync.GlobalConstants;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+/**
+ * Handle requests to display a fetched announcement.
+ */
+public class AnnouncementPresenter {
+
+  /**
+   * Display the provided snippet.
+   * @param context
+   *        The context instance to use when obtaining the NotificationManager.
+   * @param notificationID
+   *        A unique ID for this notification.
+   * @param title
+   *        The *already localized* String title. Must not be null.
+   * @param body
+   *        The *already localized* String body. Must not be null.
+   * @param uri
+   *        The URL to open when the notification is tapped.
+   */
+  public static void displayAnnouncement(final Context context,
+                                         final int notificationID,
+                                         final String title,
+                                         final String body,
+                                         final URI uri) {
+    final String ns = Context.NOTIFICATION_SERVICE;
+    final NotificationManager notificationManager = (NotificationManager) context.getSystemService(ns);
+
+    // Set pending intent associated with the notification.
+    Uri u = Uri.parse(uri.toASCIIString());
+    Intent intent = new Intent(Intent.ACTION_VIEW, u);
+
+    // Always open the link with Fennec.
+    intent.setClassName(GlobalConstants.BROWSER_INTENT_PACKAGE, GlobalConstants.BROWSER_INTENT_CLASS);
+    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
+
+    final int icon = R.drawable.icon;
+
+    // Deprecated approach to building a notification.
+    final long when = System.currentTimeMillis();
+    Notification notification = new Notification(icon, title, when);
+    notification.flags = Notification.FLAG_AUTO_CANCEL;
+    notification.setLatestEventInfo(context, title, body, contentIntent);
+
+    // Notification.Builder since API 11.
+    /*
+    Notification notification = new Notification.Builder(context)
+        .setContentTitle(title)
+        .setContentText(body)
+        .setAutoCancel(true)
+        .setContentIntent(contentIntent).getNotification();
+     */
+
+    // Send notification.
+    notificationManager.notify(notificationID, notification);
+  }
+
+  public static void displayAnnouncement(final Context context,
+                                         final Announcement snippet) {
+    final int notificationID = snippet.getId();
+    final String title = snippet.getTitle();
+    final String body = snippet.getText();
+    final URI uri = snippet.getUri();
+    AnnouncementPresenter.displayAnnouncement(context, notificationID, title, body, uri);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/AnnouncementsBroadcastReceiver.java
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Watch for notifications to start the announcements service.
+ *
+ * Some observations:
+ *
+ * "Also note that as of Android 3.0 the user needs to have started the
+ *  application at least once before your application can receive
+ *  android.intent.action.BOOT_COMPLETED events."
+ */
+public class AnnouncementsBroadcastReceiver extends BroadcastReceiver {
+
+  /**
+   * Forward the intent to an IntentService to do background processing.
+   */
+  @Override
+  public void onReceive(Context context, Intent intent) {
+    Intent service = new Intent(context, AnnouncementsBroadcastService.class);
+    service.putExtras(intent);
+    service.setAction(intent.getAction());
+    context.startService(service);
+  }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/AnnouncementsBroadcastService.java
@@ -0,0 +1,158 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.mozilla.gecko.background.BackgroundConstants;
+import org.mozilla.gecko.sync.Logger;
+
+import android.app.AlarmManager;
+import android.app.IntentService;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+/**
+ * A service which listens to broadcast intents from the system and from the
+ * browser, registering or unregistering the main
+ * {@link AnnouncementsStartReceiver} with the {@link AlarmManager}.
+ */
+public class AnnouncementsBroadcastService extends IntentService {
+  private static final String WORKER_THREAD_NAME = "AnnouncementsBroadcastServiceWorker";
+  private static final String LOG_TAG = "AnnounceBrSvc";
+
+  public AnnouncementsBroadcastService() {
+    super(WORKER_THREAD_NAME);
+  }
+
+  private void toggleAlarm(final Context context, boolean enabled) {
+    Logger.info(LOG_TAG, (enabled ? "R" : "Unr") + "egistering announcements broadcast receiver...");
+    final AlarmManager alarm = getAlarmManager(context);
+
+    final Intent service = new Intent(context, AnnouncementsStartReceiver.class);
+    final PendingIntent pending = PendingIntent.getBroadcast(context, 0, service, PendingIntent.FLAG_CANCEL_CURRENT);
+
+    if (!enabled) {
+      alarm.cancel(pending);
+      return;
+    }
+
+    final long firstEvent = System.currentTimeMillis();
+    final long pollInterval = getPollInterval(context);
+    Logger.info(LOG_TAG, "Setting inexact repeating alarm for interval " + pollInterval);
+    alarm.setInexactRepeating(AlarmManager.RTC, firstEvent, pollInterval, pending);
+  }
+
+  private static AlarmManager getAlarmManager(Context context) {
+    return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+  }
+
+  private void recordLastLaunch(final Context context) {
+    final SharedPreferences preferences = context.getSharedPreferences(AnnouncementsConstants.PREFS_BRANCH, BackgroundConstants.SHARED_PREFERENCES_MODE);
+    preferences.edit().putLong(AnnouncementsConstants.PREF_LAST_LAUNCH, System.currentTimeMillis()).commit();
+  }
+
+  public static long getPollInterval(final Context context) {
+    SharedPreferences preferences = context.getSharedPreferences(AnnouncementsConstants.PREFS_BRANCH, BackgroundConstants.SHARED_PREFERENCES_MODE);
+    return preferences.getLong(AnnouncementsConstants.PREF_ANNOUNCE_FETCH_INTERVAL_MSEC, AnnouncementsConstants.DEFAULT_ANNOUNCE_FETCH_INTERVAL_MSEC);
+  }
+
+  public static void setPollInterval(final Context context, long interval) {
+    SharedPreferences preferences = context.getSharedPreferences(AnnouncementsConstants.PREFS_BRANCH, BackgroundConstants.SHARED_PREFERENCES_MODE);
+    preferences.edit().putLong(AnnouncementsConstants.PREF_ANNOUNCE_FETCH_INTERVAL_MSEC, interval).commit();
+  }
+
+  @Override
+  protected void onHandleIntent(Intent intent) {
+    Logger.setThreadLogTag(AnnouncementsConstants.GLOBAL_LOG_TAG);
+    final String action = intent.getAction();
+    Logger.debug(LOG_TAG, "Broadcast onReceive. Intent is " + action);
+
+    if (AnnouncementsConstants.ACTION_ANNOUNCEMENTS_PREF.equals(action)) {
+      handlePrefIntent(intent);
+      return;
+    }
+
+    if (Intent.ACTION_BOOT_COMPLETED.equals(action) ||
+        Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
+      handleSystemLifetimeIntent();
+      return;
+    }
+
+    // Failure case.
+    Logger.warn(LOG_TAG, "Unknown intent " + action);
+  }
+
+  /**
+   * Handle one of the system intents to which we listen to launch our service
+   * without the browser being opened.
+   *
+   * To avoid tight coupling to Fennec, we use reflection to find
+   * <code>GeckoPreferences</code>, invoking the same code path that
+   * <code>GeckoApp</code> uses on startup to send the <i>other</i>
+   * notification to which we listen.
+   *
+   * All of this is neatly wrapped in <code>try…catch</code>, so this code
+   * will run safely without a Firefox build installed.
+   */
+  protected void handleSystemLifetimeIntent() {
+    // Ask the browser to tell us the current state of the preference.
+    try {
+      Class<?> geckoPreferences = Class.forName(BackgroundConstants.GECKO_PREFERENCES_CLASS);
+      Method broadcastSnippetsPref = geckoPreferences.getMethod(BackgroundConstants.GECKO_BROADCAST_METHOD, Context.class);
+      broadcastSnippetsPref.invoke(null, this);
+      return;
+    } catch (ClassNotFoundException e) {
+      Logger.error(LOG_TAG, "Class " + BackgroundConstants.GECKO_PREFERENCES_CLASS + " not found!");
+      return;
+    } catch (NoSuchMethodException e) {
+      Logger.error(LOG_TAG, "Method " + BackgroundConstants.GECKO_PREFERENCES_CLASS + "/" + BackgroundConstants.GECKO_BROADCAST_METHOD + " not found!");
+      return;
+    } catch (IllegalArgumentException e) {
+      // Fall through.
+    } catch (IllegalAccessException e) {
+      // Fall through.
+    } catch (InvocationTargetException e) {
+      // Fall through.
+    }
+    Logger.error(LOG_TAG, "Got exception invoking " + BackgroundConstants.GECKO_BROADCAST_METHOD + ".");
+  }
+
+  /**
+   * Handle the intent sent by the browser when it wishes to notify us
+   * of the value of the user preference. Look at the value and toggle the
+   * alarm service accordingly.
+   */
+  protected void handlePrefIntent(Intent intent) {
+    recordLastLaunch(this);               // TODO: wrong place!
+
+    if (!intent.hasExtra("enabled")) {
+      Logger.warn(LOG_TAG, "Got ANNOUNCEMENTS_PREF intent without enabled. Ignoring.");
+      return;
+    }
+
+    final boolean enabled = intent.getBooleanExtra("enabled", true);
+    Logger.debug(LOG_TAG, intent.getStringExtra("branch") + "/" +
+                          intent.getStringExtra("pref")   + " = " +
+                          (intent.hasExtra("enabled") ? enabled : ""));
+
+    toggleAlarm(this, enabled);
+
+    // Primarily intended for debugging and testing, but this doesn't do any harm.
+    if (!enabled) {
+      Logger.info(LOG_TAG, "!enabled: clearing last fetch.");
+      final SharedPreferences sharedPreferences = this.getSharedPreferences(AnnouncementsConstants.PREFS_BRANCH,
+                                                                            BackgroundConstants.SHARED_PREFERENCES_MODE);
+      final Editor editor = sharedPreferences.edit();
+      editor.remove(AnnouncementsConstants.PREF_LAST_FETCH);
+      editor.remove(AnnouncementsConstants.PREF_EARLIEST_NEXT_ANNOUNCE_FETCH);
+      editor.commit();
+    }
+  }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/AnnouncementsConstants.java
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import org.mozilla.gecko.sync.GlobalConstants;
+
+import android.app.AlarmManager;
+
+public class AnnouncementsConstants {
+  public static final String GLOBAL_LOG_TAG = "GeckoAnnounce";
+  public static final String ACTION_ANNOUNCEMENTS_PREF = "org.mozilla.gecko.ANNOUNCEMENTS_PREF";
+
+  static final String PREFS_BRANCH = "background";
+  static final String PREF_LAST_FETCH  = "last_fetch";
+  static final String PREF_LAST_LAUNCH = "last_firefox_launch";
+  static final String PREF_ANNOUNCE_SERVER_BASE_URL  = "announce_server_base_url";
+  static final String PREF_EARLIEST_NEXT_ANNOUNCE_FETCH = "earliest_next_announce_fetch";
+  static final String PREF_ANNOUNCE_FETCH_INTERVAL_MSEC = "announce_fetch_interval_msec";
+
+  static final String DEFAULT_ANNOUNCE_SERVER_BASE_URL = "https://campaigns.services.mozilla.com/announce/";
+  public static final String ANNOUNCE_PROTOCOL_VERSION = "1";
+  public static final String ANNOUNCE_APPLICATION = "android";
+  public static final String ANNOUNCE_PATH_SUFFIX = AnnouncementsConstants.ANNOUNCE_PROTOCOL_VERSION + "/" +
+                                                    AnnouncementsConstants.ANNOUNCE_APPLICATION + "/";
+
+  public static final long DEFAULT_ANNOUNCE_FETCH_INTERVAL_MSEC = AlarmManager.INTERVAL_HALF_DAY;
+  public static final long DEFAULT_BACKOFF_MSEC = 2 * 24 * 60 * 60 * 1000;   // Two days. Used if no Retry-After header.
+
+  public static final String ANNOUNCE_USER_AGENT = "Firefox Announcements " + GlobalConstants.MOZ_APP_VERSION;
+  public static final String ANNOUNCE_CHANNEL = GlobalConstants.MOZ_UPDATE_CHANNEL.replace("default", GlobalConstants.MOZ_OFFICIAL_BRANDING ? "release" : "dev");
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/AnnouncementsFetchDelegate.java
@@ -0,0 +1,40 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import java.util.List;
+import java.util.Locale;
+
+public interface AnnouncementsFetchDelegate {
+  /**
+   * @return the timestamp of the last fetch in milliseconds.
+   */
+  public long getLastFetch();
+
+  /**
+   * @return the current system locale (e.g., en_us).
+   */
+  public Locale getLocale();
+
+  /**
+   * @return the User-Agent header to use for the request.
+   */
+  public String getUserAgent();
+
+  /**
+   * @return the server URL to interrogate, including path.
+   */
+  public String getServiceURL();
+
+  /*
+   * Callback methods.
+   */
+  public void onNoNewAnnouncements(long fetched);
+  public void onNewAnnouncements(List<Announcement> snippets, long fetched);
+  public void onLocalError(Exception e);
+  public void onRemoteError(Exception e);
+  public void onRemoteFailure(int status);
+  public void onBackoff(int retryAfterInSeconds);
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/AnnouncementsFetchResourceDelegate.java
@@ -0,0 +1,160 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.mozilla.gecko.sync.ExtendedJSONObject;
+import org.mozilla.gecko.sync.Logger;
+import org.mozilla.gecko.sync.NonArrayJSONException;
+import org.mozilla.gecko.sync.net.BaseResource;
+import org.mozilla.gecko.sync.net.Resource;
+import org.mozilla.gecko.sync.net.SyncResourceDelegate;
+import org.mozilla.gecko.sync.net.SyncResponse;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.client.ClientProtocolException;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
+import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
+import ch.boye.httpclientandroidlib.impl.cookie.DateUtils;
+
+/**
+ * Converts HTTP resource callbacks into AnnouncementsFetchDelegate callbacks.
+ */
+public class AnnouncementsFetchResourceDelegate extends SyncResourceDelegate {
+  private static final String ACCEPT_HEADER = "application/json;charset=utf-8";
+
+  private static final String LOG_TAG = "AnnounceFetchRD";
+
+  protected final long startTime;
+  protected AnnouncementsFetchDelegate delegate;
+
+  public AnnouncementsFetchResourceDelegate(Resource resource, AnnouncementsFetchDelegate delegate) {
+    super(resource);
+    this.startTime = System.currentTimeMillis();
+    this.delegate  = delegate;
+  }
+
+  @Override
+  public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
+    super.addHeaders(request, client);
+
+    // The basics.
+    request.addHeader("User-Agent",      delegate.getUserAgent());
+    request.addHeader("Accept-Language", delegate.getLocale().toString());
+    request.addHeader("Accept",          ACCEPT_HEADER);
+
+    // Set If-Modified-Since to avoid re-fetching content.
+    final long ifModifiedSince = delegate.getLastFetch();
+    if (ifModifiedSince > 0) {
+      final String imsHeader = DateUtils.formatDate(new Date(ifModifiedSince));
+      Logger.info(LOG_TAG, "If-Modified-Since: " + imsHeader);
+      request.addHeader("If-Modified-Since", imsHeader);
+    }
+
+    // Just in case.
+    request.removeHeaders("Cookie");
+  }
+
+  private List<Announcement> parseBody(ExtendedJSONObject body) throws NonArrayJSONException {
+    List<Announcement> out = new ArrayList<Announcement>(1);
+    JSONArray snippets = body.getArray("announcements");
+    if (snippets == null) {
+      Logger.warn(LOG_TAG, "Missing announcements body. Returning empty.");
+      return out;
+    }
+
+    for (Object s : snippets) {
+      try {
+        out.add(Announcement.parseAnnouncement(new ExtendedJSONObject((JSONObject) s)));
+      } catch (Exception e) {
+        Logger.warn(LOG_TAG, "Malformed announcement or display failed. Skipping.", e);
+      }
+    }
+    return out;
+  }
+
+  @Override
+  public void handleHttpResponse(HttpResponse response) {
+    SyncResponse r = new SyncResponse(response);    // For convenience.
+
+    try {
+      final int statusCode = r.getStatusCode();
+      Logger.debug(LOG_TAG, "Got announcements response: " + statusCode);
+
+      if (statusCode == 204 || statusCode == 304) {
+        BaseResource.consumeEntity(response);
+        delegate.onNoNewAnnouncements(startTime);
+        return;
+      }
+
+      if (statusCode == 200) {
+        final List<Announcement> snippets;
+        try {
+          snippets = parseBody(r.jsonObjectBody());
+        } catch (Exception e) {
+          delegate.onRemoteError(e);
+          return;
+        }
+        delegate.onNewAnnouncements(snippets, startTime);
+        return;
+      }
+
+      if (statusCode == 400 || statusCode == 405) {
+        // We did something wrong.
+        Logger.warn(LOG_TAG, "We did something wrong. Oh dear.");
+        // Fall through.
+      }
+
+      if (statusCode == 503 || statusCode == 500) {
+        Logger.warn(LOG_TAG, "Server issue: " + r.body());
+        delegate.onBackoff(r.retryAfterInSeconds());
+        return;
+      }
+
+      // Otherwise, clean up.
+      delegate.onRemoteFailure(statusCode);
+
+    } catch (Exception e) {
+      Logger.warn(LOG_TAG, "Failed to extract body.", e);
+      delegate.onRemoteError(e);
+    }
+  }
+
+  @Override
+  public void handleHttpProtocolException(ClientProtocolException e) {
+    Logger.warn(LOG_TAG, "Protocol exception.", e);
+    delegate.onLocalError(e);
+  }
+
+  @Override
+  public void handleHttpIOException(IOException e) {
+    Logger.warn(LOG_TAG, "IO exception.", e);
+    delegate.onLocalError(e);
+  }
+
+  @Override
+  public void handleTransportException(GeneralSecurityException e) {
+    Logger.warn(LOG_TAG, "Transport exception.", e);
+    // Class this as a remote error, because it's probably something odd
+    // with SSL negotiation.
+    delegate.onRemoteError(e);
+  }
+
+  /**
+   * Be very thorough in case the superclass implementation changes.
+   * We never want this to be an authenticated request.
+   */
+  @Override
+  public String getCredentials() {
+    return null;
+  }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/AnnouncementsFetcher.java
@@ -0,0 +1,89 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+
+import org.mozilla.gecko.sync.GlobalConstants;
+import org.mozilla.gecko.sync.Logger;
+import org.mozilla.gecko.sync.net.BaseResource;
+
+public class AnnouncementsFetcher {
+  private static final String LOG_TAG = "AnnounceFetch";
+  private static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
+
+  public static URI getSnippetURI(String base, String channel,
+                                  String version, String platform,
+                                  int idleDays)
+    throws URISyntaxException {
+    try {
+      final String c = URLEncoder.encode(channel, "UTF-8");
+      final String v = URLEncoder.encode(version, "UTF-8");
+      final String p = URLEncoder.encode(platform, "UTF-8");
+      final String s = base + c + "/" + v + "/" + p + ((idleDays == -1) ? "" : ("?idle=" + idleDays));
+      return new URI(s);
+    } catch (UnsupportedEncodingException e) {
+      // Nonsense.
+      return null;
+    }
+  }
+
+  public static URI getAnnounceURI(final String baseURL, final long lastLaunch) throws URISyntaxException {
+    final String channel = getChannel();
+    final String version = getVersion();
+    final String platform = getPlatform();
+    final int idleDays = getIdleDays(lastLaunch);
+
+    Logger.debug(LOG_TAG, "Fetch URI: idle for " + idleDays + " days.");
+    return getSnippetURI(baseURL, channel, version, platform, idleDays);
+  }
+
+  protected static String getChannel() {
+    return AnnouncementsConstants.ANNOUNCE_CHANNEL;
+  }
+
+  protected static String getVersion() {
+    return GlobalConstants.MOZ_APP_VERSION;
+  }
+
+  protected static String getPlatform() {
+    return GlobalConstants.ANDROID_CPU_ARCH;
+  }
+
+  protected static int getIdleDays(final long lastLaunch) {
+    if (lastLaunch == 0) {
+      return -1;
+    }
+    final long idleMillis = System.currentTimeMillis() - lastLaunch;
+    return (int) (idleMillis / MILLISECONDS_PER_DAY);
+  }
+
+  public static void fetchAnnouncements(URI uri, AnnouncementsFetchDelegate delegate) {
+    BaseResource r = new BaseResource(uri);
+    r.delegate = new AnnouncementsFetchResourceDelegate(r, delegate);
+    r.getBlocking();
+  }
+
+  /**
+   * Synchronous.
+   */
+  public static void fetchAndProcessAnnouncements(long lastLaunch,
+                                                  AnnouncementsFetchDelegate delegate) {
+    final long now = System.currentTimeMillis();
+    Logger.debug(LOG_TAG, "Fetching announcements. Last launch: " + lastLaunch + "; now: " + now);
+    try {
+      final String base = delegate.getServiceURL();
+      final URI uri = getAnnounceURI(base, lastLaunch);
+      Logger.info(LOG_TAG, "Fetching announcements from " + uri.toASCIIString());
+      fetchAnnouncements(uri, delegate);
+    } catch (URISyntaxException e) {
+      Logger.warn(LOG_TAG, "Couldn't create URL.", e);
+      return;
+    }
+  }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/AnnouncementsService.java
@@ -0,0 +1,281 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.util.List;
+import java.util.Locale;
+
+import org.mozilla.gecko.background.BackgroundConstants;
+import org.mozilla.gecko.sync.Logger;
+
+import android.app.IntentService;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Build;
+import android.os.IBinder;
+
+/**
+ * A Service to periodically check for new published announcements,
+ * presenting them to the user if local conditions permit.
+ *
+ * We extend IntentService, rather than just Service, because this gives us
+ * a worker thread to avoid main-thread networking.
+ *
+ * Yes, even though we're in an alarm-triggered service, it still counts
+ * as main-thread.
+ *
+ * The operation of this service is as follows:
+ *
+ * 0. Decide if a request should be made.
+ * 1. Compute the arguments to the request. This includes enough
+ *    pertinent details to allow the server to pre-filter a message
+ *    set, recording enough tracking details to compute statistics.
+ * 2. Issue the request. If this succeeds with a 200 or 204, great;
+ *    track that timestamp for the next run through Step 0.
+ * 3. Process any received messages.
+ *
+ * Message processing is as follows:
+ *
+ * 0. Decide if message display should occur. This might involve
+ *    user preference or other kinds of environmental factors.
+ * 1. Use the AnnouncementPresenter to open the announcement.
+ *
+ * Future:
+ * * Persisting of multiple announcements.
+ * * Prioritization.
+ */
+public class AnnouncementsService extends IntentService implements AnnouncementsFetchDelegate {
+  private static final String WORKER_THREAD_NAME = "AnnouncementsServiceWorker";
+  private static final String LOG_TAG = "AnnounceService";
+
+  private static final long MINIMUM_FETCH_INTERVAL_MSEC = 60 * 60 * 1000;   // 1 hour.
+
+  public AnnouncementsService() {
+    super(WORKER_THREAD_NAME);
+    Logger.setThreadLogTag(AnnouncementsConstants.GLOBAL_LOG_TAG);
+    Logger.debug(LOG_TAG, "Creating AnnouncementsService.");
+  }
+
+  public boolean shouldFetchAnnouncements() {
+    final long now = System.currentTimeMillis();
+
+    if (!backgroundDataIsEnabled()) {
+      Logger.debug(LOG_TAG, "Background data not possible. Skipping.");
+      return false;
+    }
+
+    // Don't fetch if we were told to back off.
+    if (getEarliestNextFetch() > now) {
+      return false;
+    }
+
+    // Don't do anything if we haven't waited long enough.
+    final long lastFetch = getLastFetch();
+
+    // Just in case the alarm manager schedules us more frequently, or something
+    // goes awry with relaunches.
+    if ((now - lastFetch) < MINIMUM_FETCH_INTERVAL_MSEC) {
+      Logger.debug(LOG_TAG, "Returning: minimum fetch interval of " + MINIMUM_FETCH_INTERVAL_MSEC + "ms not met.");
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Display the first valid announcement in the list.
+   */
+  protected void processAnnouncements(final List<Announcement> announcements) {
+    if (announcements == null) {
+      Logger.warn(LOG_TAG, "No announcements to present.");
+      return;
+    }
+
+    boolean presented = false;
+    for (Announcement an : announcements) {
+      // Do this so we at least log, rather than just returning.
+      if (presented) {
+        Logger.warn(LOG_TAG, "Skipping announcement \"" + an.getTitle() + "\": one already shown.");
+        continue;
+      }
+      if (Announcement.isValidAnnouncement(an)) {
+        presented = true;
+        AnnouncementPresenter.displayAnnouncement(this, an);
+      }
+    }
+  }
+
+  /**
+   * If it's time to do a fetch -- we've waited long enough,
+   * we're allowed to use background data, etc. -- then issue
+   * a fetch. The subsequent background check is handled implicitly
+   * by the AlarmManager.
+   */
+  @Override
+  public void onHandleIntent(Intent intent) {
+    Logger.setThreadLogTag(AnnouncementsConstants.GLOBAL_LOG_TAG);
+    Logger.debug(LOG_TAG, "Running AnnouncementsService.");
+
+    if (!shouldFetchAnnouncements()) {
+      Logger.debug(LOG_TAG, "Not fetching.");
+      return;
+    }
+
+    // Otherwise, grab our announcements URL and process the contents.
+    AnnouncementsFetcher.fetchAndProcessAnnouncements(getLastLaunch(), this);
+  }
+
+  @Override
+  public void onDestroy() {
+    super.onDestroy();
+  }
+
+  @Override
+  public IBinder onBind(Intent intent) {
+    return null;
+  }
+
+  /**
+   * Returns true if the OS will allow us to perform background
+   * data operations. This logic varies by OS version.
+   */
+  protected boolean backgroundDataIsEnabled() {
+    ConnectivityManager connectivity = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
+    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+      return connectivity.getBackgroundDataSetting();
+    }
+    NetworkInfo networkInfo = connectivity.getActiveNetworkInfo();
+    if (networkInfo == null) {
+      return false;
+    }
+    return networkInfo.isAvailable();
+  }
+
+  protected long getLastLaunch() {
+    return getSharedPreferences().getLong(AnnouncementsConstants.PREF_LAST_LAUNCH, 0);
+  }
+
+  private SharedPreferences getSharedPreferences() {
+    return this.getSharedPreferences(AnnouncementsConstants.PREFS_BRANCH, BackgroundConstants.SHARED_PREFERENCES_MODE);
+  }
+
+  @Override
+  protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+    super.dump(fd, writer, args);
+
+    final long lastFetch = getLastFetch();
+    final long lastLaunch = getLastLaunch();
+    writer.write("AnnouncementsService: last fetch " + lastFetch +
+                 ", last Firefox activity: " + lastLaunch + "\n");
+  }
+
+  protected void setEarliestNextFetch(final long earliestInMsec) {
+    this.getSharedPreferences().edit().putLong(AnnouncementsConstants.PREF_EARLIEST_NEXT_ANNOUNCE_FETCH, earliestInMsec).commit();
+  }
+
+  protected long getEarliestNextFetch() {
+    return this.getSharedPreferences().getLong(AnnouncementsConstants.PREF_EARLIEST_NEXT_ANNOUNCE_FETCH, 0L);
+  }
+
+  protected void setLastFetch(final long fetch) {
+    this.getSharedPreferences().edit().putLong(AnnouncementsConstants.PREF_LAST_FETCH, fetch).commit();
+  }
+
+  @Override
+  public long getLastFetch() {
+    return getSharedPreferences().getLong(AnnouncementsConstants.PREF_LAST_FETCH, 0L);
+  }
+
+  /**
+   * Use this to write the persisted server URL, overriding
+   * the default value.
+   * @param url a URI identifying the full request path, e.g.,
+   *            "http://foo.com:1234/announce/"
+   */
+  public void setAnnouncementsServerBaseURL(final URI url) {
+    if (url == null) {
+      throw new IllegalArgumentException("url cannot be null.");
+    }
+    final String scheme = url.getScheme();
+    if (scheme == null) {
+      throw new IllegalArgumentException("url must have a scheme.");
+    }
+    if (!scheme.equalsIgnoreCase("http") && !scheme.equalsIgnoreCase("https")) {
+      throw new IllegalArgumentException("url must be http or https.");
+    }
+    SharedPreferences p = this.getSharedPreferences();
+    p.edit().putString(AnnouncementsConstants.PREF_ANNOUNCE_SERVER_BASE_URL, url.toASCIIString()).commit();
+  }
+
+  /**
+   * Return the service URL, including protocol version and application identifier. E.g.,
+   *
+   *   "https://campaigns.services.mozilla.com/announce/1/android/"
+   */
+  @Override
+  public String getServiceURL() {
+    SharedPreferences p = this.getSharedPreferences();
+    String base = p.getString(AnnouncementsConstants.PREF_ANNOUNCE_SERVER_BASE_URL, AnnouncementsConstants.DEFAULT_ANNOUNCE_SERVER_BASE_URL);
+    return base + AnnouncementsConstants.ANNOUNCE_PATH_SUFFIX;
+  }
+
+  @Override
+  public Locale getLocale() {
+    return Locale.getDefault();
+  }
+
+  @Override
+  public String getUserAgent() {
+    return AnnouncementsConstants.ANNOUNCE_USER_AGENT;
+  }
+
+  @Override
+  public void onNoNewAnnouncements(long fetched) {
+    Logger.info(LOG_TAG, "No new announcements to display.");
+    setLastFetch(fetched);
+  }
+
+  @Override
+  public void onNewAnnouncements(List<Announcement> announcements, long fetched) {
+    Logger.info(LOG_TAG, "Processing announcements: " + announcements.size());
+    setLastFetch(fetched);
+    processAnnouncements(announcements);
+  }
+
+  @Override
+  public void onRemoteFailure(int status) {
+    // Bump our fetch timestamp.
+    Logger.warn(LOG_TAG, "Got remote fetch status " + status + "; bumping fetch time.");
+    setLastFetch(System.currentTimeMillis());
+  }
+
+  @Override
+  public void onRemoteError(Exception e) {
+    // Bump our fetch timestamp.
+    Logger.warn(LOG_TAG, "Error processing response.", e);
+    setLastFetch(System.currentTimeMillis());
+  }
+
+  @Override
+  public void onLocalError(Exception e) {
+    Logger.error(LOG_TAG, "Got exception in fetch.", e);
+    // Do nothing yet, so we'll retry.
+  }
+
+  @Override
+  public void onBackoff(int retryAfterInSeconds) {
+    Logger.info(LOG_TAG, "Got retry after: " + retryAfterInSeconds);
+    final long delayInMsec = Math.max(retryAfterInSeconds * 1000, AnnouncementsConstants.DEFAULT_BACKOFF_MSEC);
+    final long fuzzedBackoffInMsec = delayInMsec + Math.round(((double) delayInMsec * 0.25d * Math.random()));
+    Logger.debug(LOG_TAG, "Fuzzed backoff: " + fuzzedBackoffInMsec + "ms.");
+    setEarliestNextFetch(fuzzedBackoffInMsec + System.currentTimeMillis());
+  }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/background/announcements/AnnouncementsStartReceiver.java
@@ -0,0 +1,27 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.background.announcements;
+
+import org.mozilla.gecko.sync.Logger;
+
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Start the announcements service when instructed by the {@link AlarmManager}.
+ */
+public class AnnouncementsStartReceiver extends BroadcastReceiver {
+
+  private static final String LOG_TAG = "AnnounceStartRec";
+
+  @Override
+  public void onReceive(Context context, Intent intent) {
+    Logger.debug(LOG_TAG, "AnnouncementsStartReceiver.onReceive().");
+    Intent service = new Intent(context, AnnouncementsService.class);
+    context.startService(service);
+  }
+}
--- a/mobile/android/base/sync/net/BaseResource.java
+++ b/mobile/android/base/sync/net/BaseResource.java
@@ -306,16 +306,26 @@ public class BaseResource implements Res
   }
 
   @Override
   public void get() {
     Logger.debug(LOG_TAG, "HTTP GET " + this.uri.toASCIIString());
     this.go(new HttpGet(this.uri));
   }
 
+  /**
+   * Perform an HTTP GET as with {@link BaseResource#get()}, returning only
+   * after callbacks have been invoked.
+   */
+  public void getBlocking() {
+    // Until we use the asynchronous Apache HttpClient, we can simply call
+    // through.
+    this.get();
+  }
+
   @Override
   public void delete() {
     Logger.debug(LOG_TAG, "HTTP DELETE " + this.uri.toASCIIString());
     this.go(new HttpDelete(this.uri));
   }
 
   @Override
   public void post(HttpEntity body) {
--- a/mobile/android/services/java-sources.mn
+++ b/mobile/android/services/java-sources.mn
@@ -1,8 +1,19 @@
+background/announcements/Announcement.java
+background/announcements/AnnouncementPresenter.java
+background/announcements/AnnouncementsBroadcastReceiver.java
+background/announcements/AnnouncementsBroadcastService.java
+background/announcements/AnnouncementsConstants.java
+background/announcements/AnnouncementsFetchDelegate.java
+background/announcements/AnnouncementsFetcher.java
+background/announcements/AnnouncementsFetchResourceDelegate.java
+background/announcements/AnnouncementsService.java
+background/announcements/AnnouncementsStartReceiver.java
+background/BackgroundConstants.java
 sync/AlreadySyncingException.java
 sync/CollectionKeys.java
 sync/CommandProcessor.java
 sync/CommandRunner.java
 sync/config/AccountPickler.java
 sync/config/activities/SelectEnginesActivity.java
 sync/config/ClientRecordTerminator.java
 sync/config/ConfigurationMigrator.java
--- a/mobile/android/services/manifests/AnnouncementsAndroidManifest_activities.xml.in
+++ b/mobile/android/services/manifests/AnnouncementsAndroidManifest_activities.xml.in
@@ -0,0 +1,20 @@
+        <!--
+             As well as these system actions, we also listen for pref notifications
+             sent by Fennec: org.mozilla.gecko.SNIPPETS_PREF.
+          -->
+        <receiver android:name="org.mozilla.gecko.background.announcements.AnnouncementsBroadcastReceiver" >
+            <intent-filter>
+                <!-- Startup. -->
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+            <intent-filter>
+                <!-- SD card remounted. -->
+                <action android:name="android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE" />
+            </intent-filter>
+            <intent-filter >
+              <action android:name="org.mozilla.gecko.ANNOUNCEMENTS_PREF" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="org.mozilla.gecko.background.announcements.AnnouncementsStartReceiver" >
+        </receiver>
--- a/mobile/android/services/manifests/AnnouncementsAndroidManifest_permissions.xml.in
+++ b/mobile/android/services/manifests/AnnouncementsAndroidManifest_permissions.xml.in
@@ -0,0 +1,2 @@
+    <!-- So we can start our service. -->
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
--- a/mobile/android/services/manifests/AnnouncementsAndroidManifest_services.xml.in
+++ b/mobile/android/services/manifests/AnnouncementsAndroidManifest_services.xml.in
@@ -0,0 +1,8 @@
+        <service
+		        android:exported="false"
+		        android:name="org.mozilla.gecko.background.announcements.AnnouncementsService" >
+        </service>
+        <service
+		        android:exported="false"
+		        android:name="org.mozilla.gecko.background.announcements.AnnouncementsBroadcastService" >
+        </service>