VCardService.java revision 7c819a1a434e02c54f6d216aa3b1a0d08cc93f50
1f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa/* 2f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * Copyright (C) 2010 The Android Open Source Project 3f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * 4f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); 5f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * you may not use this file except in compliance with the License. 6f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * You may obtain a copy of the License at 7f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * 8f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0 9f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * 10f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * Unless required by applicable law or agreed to in writing, software 11f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, 12f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * See the License for the specific language governing permissions and 14f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa * limitations under the License. 15f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa */ 161b918e58f4a3ae8d32af83f6f69bbf2de57a94f9Daisuke Miyakawapackage com.android.contacts.vcard; 17f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa 187c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawaimport com.android.contacts.R; 197c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 20f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawaimport android.app.Service; 21f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawaimport android.content.Intent; 22476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawaimport android.os.Handler; 23f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawaimport android.os.IBinder; 24476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawaimport android.os.Message; 25476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawaimport android.os.Messenger; 26f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawaimport android.util.Log; 27f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawaimport android.widget.Toast; 28f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa 29aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawaimport java.io.File; 30aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawaimport java.util.Date; 317c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawaimport java.util.HashMap; 327c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawaimport java.util.Map; 337c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawaimport java.util.concurrent.ExecutorService; 347c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawaimport java.util.concurrent.Executors; 357c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawaimport java.util.concurrent.RejectedExecutionException; 361b918e58f4a3ae8d32af83f6f69bbf2de57a94f9Daisuke Miyakawa 37f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa/** 387c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa * The class responsible for handling vCard import/export requests. 397c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa * 407c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa * This Service creates one ImportRequest/ExportRequest object (as Runnable) per request and push 417c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa * it to {@link ExecutorService} with single thread executor. The executor handles each request 427c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa * one by one, and notifies users when needed. 43f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa */ 447c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa// TODO: Using IntentService looks simpler than using Service + ServiceConnection though this 457c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa// works fine enough. Investigate the feasibility. 46d8fb81a0024d30c027ea6ebf57d29d3ff10453fbDaisuke Miyakawapublic class VCardService extends Service { 477c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private final static String LOG_TAG = "VCardService"; 48f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa 49ef41f8866e8e7d52e04907f7282adcf5f4749f25Daisuke Miyakawa /* package */ static final int MSG_IMPORT_REQUEST = 1; 50d8fb81a0024d30c027ea6ebf57d29d3ff10453fbDaisuke Miyakawa /* package */ static final int MSG_EXPORT_REQUEST = 2; 5118b5190d6ed37be04d153a5d6f205076b38ac479Daisuke Miyakawa /* package */ static final int MSG_CANCEL_IMPORT_REQUEST = 3; 52f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa 53d8fb81a0024d30c027ea6ebf57d29d3ff10453fbDaisuke Miyakawa /* package */ static final int IMPORT_NOTIFICATION_ID = 1000; 54d8fb81a0024d30c027ea6ebf57d29d3ff10453fbDaisuke Miyakawa /* package */ static final int EXPORT_NOTIFICATION_ID = 1001; 55f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa 56aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa /* package */ static final String CACHE_FILE_PREFIX = "import_tmp_"; 57f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa 587c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa public class RequestHandler extends Handler { 59476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa @Override 60476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa public void handleMessage(Message msg) { 61476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa switch (msg.what) { 62ef41f8866e8e7d52e04907f7282adcf5f4749f25Daisuke Miyakawa case MSG_IMPORT_REQUEST: { 637c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa handleImportRequest((ImportRequest)msg.obj); 64476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa break; 65915723665339c73c9bdebc7bf8ef56c414602c2cDaisuke Miyakawa } 66d8fb81a0024d30c027ea6ebf57d29d3ff10453fbDaisuke Miyakawa case MSG_EXPORT_REQUEST: { 677c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa handleExportRequest((ExportRequest)msg.obj); 68d8fb81a0024d30c027ea6ebf57d29d3ff10453fbDaisuke Miyakawa break; 69d8fb81a0024d30c027ea6ebf57d29d3ff10453fbDaisuke Miyakawa } 7018b5190d6ed37be04d153a5d6f205076b38ac479Daisuke Miyakawa case MSG_CANCEL_IMPORT_REQUEST: { 717c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa handleCancelAllImportRequest(); 7218b5190d6ed37be04d153a5d6f205076b38ac479Daisuke Miyakawa break; 7318b5190d6ed37be04d153a5d6f205076b38ac479Daisuke Miyakawa } 747c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa // TODO: add cancel capability for export.. 75d8fb81a0024d30c027ea6ebf57d29d3ff10453fbDaisuke Miyakawa default: { 76aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa Log.w(LOG_TAG, "Received unknown request, ignoring it."); 77476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa super.hasMessages(msg.what); 78d8fb81a0024d30c027ea6ebf57d29d3ff10453fbDaisuke Miyakawa } 79476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa } 80f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa } 81476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa } 82f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa 837c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private final Handler mHandler = new RequestHandler(); 847c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private final Messenger mMessenger = new Messenger(mHandler); 857c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa // Should be single thread, as we don't want to simultaneously handle import and export 867c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa // requests. 877c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); 887c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 897c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private int mCurrentJobId; 907c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private final Map<Integer, ImportProcessor> mRunningJobMapForImport = 917c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa new HashMap<Integer, ImportProcessor>(); 927c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private final Map<Integer, ExportProcessor> mRunningJobMapForExport = 937c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa new HashMap<Integer, ExportProcessor>(); 94476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa 95476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa @Override 96476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa public int onStartCommand(Intent intent, int flags, int id) { 97476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa return START_STICKY; 98f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa } 99f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa 100f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa @Override 101f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa public IBinder onBind(Intent intent) { 102476004be0c4907b462b3d699671d9e1cff1a7bd7Daisuke Miyakawa return mMessenger.getBinder(); 103f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa } 104aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa 105aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa @Override 106aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa public void onDestroy() { 1077c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, "VCardService is finishing()"); 1087c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa cancelRequestsAndshutdown(); 109aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa clearCache(); 110aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa super.onDestroy(); 111aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa } 112aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa 1137c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private synchronized void handleImportRequest(ImportRequest request) { 1147c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, String.format("Received vCard import request. id: %d", mCurrentJobId)); 1157c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa final ImportProcessor importProcessor = 1167c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa new ImportProcessor(this, request, mCurrentJobId); 1177c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa try { 1187c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mExecutorService.submit(importProcessor); 1197c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } catch (RejectedExecutionException e) { 1207c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.w(LOG_TAG, "vCard import request is rejected.", e); 1217c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa // TODO: a little unkind to show Toast in this case, which is shown just a moment. 1227c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa // Ideally we should show some persistent something users can notice more easily. 1237c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Toast.makeText(this, getString(R.string.vcard_import_request_rejected_message), 1247c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Toast.LENGTH_LONG).show(); 1257c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa return; 1267c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1277c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mRunningJobMapForImport.put(mCurrentJobId, importProcessor); 1287c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mCurrentJobId++; 1297c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa // TODO: Ideally we should detect the current status of import/export and show "started" 1307c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa // when we can import right now and show "will start" when we cannot. 1317c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Toast.makeText(this, getString(R.string.vcard_import_will_start_message), 1327c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Toast.LENGTH_LONG).show(); 1337c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1347c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 1357c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private synchronized void handleExportRequest(ExportRequest request) { 1367c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, String.format("Received vCard export request. id: %d", mCurrentJobId)); 1377c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa final ExportProcessor exportProcessor = 1387c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa new ExportProcessor(this, request, mCurrentJobId); 1397c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa try { 1407c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mExecutorService.submit(exportProcessor); 1417c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } catch (RejectedExecutionException e) { 1427c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.w(LOG_TAG, "vCard export request is rejected.", e); 1437c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Toast.makeText(this, getString(R.string.vcard_export_request_rejected_message), 1447c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Toast.LENGTH_LONG).show(); 1457c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa return; 1467c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1477c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mRunningJobMapForExport.put(mCurrentJobId, exportProcessor); 1487c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mCurrentJobId++; 1497c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa // See the comment in handleImportRequest() 1507c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Toast.makeText(this, getString(R.string.vcard_export_will_start_message), 1517c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Toast.LENGTH_LONG).show(); 1527c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1537c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 1547c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private synchronized void handleCancelAllImportRequest() { 1557c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, "Received cancel import request."); 1567c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa cancelAllImportRequest(); 1577c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mRunningJobMapForImport.clear(); 1587c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1597c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 1607c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private void cancelAllImportRequest() { 1617c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa for (final Map.Entry<Integer, ImportProcessor> entry : 1627c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mRunningJobMapForImport.entrySet()) { 1637c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa final int jobId = entry.getKey(); 1647c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa final ImportProcessor importProcessor = entry.getValue(); 1657c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa importProcessor.cancel(); 1667c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, String.format("Canceling job %d", jobId)); 1677c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1687c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1697c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 1707c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private void cancelAllExportRequest() { 1717c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa for (final Map.Entry<Integer, ExportProcessor> entry : 1727c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mRunningJobMapForExport.entrySet()) { 1737c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa final int jobId = entry.getKey(); 1747c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa final ExportProcessor exportProcessor = entry.getValue(); 1757c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa exportProcessor.cancel(); 1767c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, String.format("Canceling job %d", jobId)); 1777c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1787c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1797c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 1807c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa /* package */ synchronized void handleFinishImportNotification( 1817c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa int jobId, boolean successful) { 1827c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, String.format("Received vCard import finish notification (id: %d). " 1837c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa + "Result: %b", jobId, (successful ? "success" : "failure"))); 1847c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa if (mRunningJobMapForImport.remove(jobId) == null) { 1857c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.w(LOG_TAG, String.format("Tried to remove unknown job (id: %d)", jobId)); 1867c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1877c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1887c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 1897c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa /* package */ synchronized void handleFinishExportNotification( 1907c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa int jobId, boolean successful) { 1917c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, String.format("Received vCard export finish notification (id: %d). " 1927c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa + "Result: %b", jobId, (successful ? "success" : "failure"))); 1937c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa if (mRunningJobMapForExport.remove(jobId) == null) { 1947c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.w(LOG_TAG, String.format("Tried to remove unknown job (id: %d)", jobId)); 1957c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1967c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 1977c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 1987c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa /** 1997c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa * Cancels all the import/export requests and call {@link ExecutorService#shutdown()}, which 2007c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa * means this Service becomes no longer ready for import/export requests. Mainly used in 2017c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa * onDestroy(). 2027c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa */ 2037c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa private synchronized void cancelRequestsAndshutdown() { 2047c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa synchronized (this) { 2057c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa if (mRunningJobMapForImport.size() > 0) { 2067c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, 2077c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa String.format("Cancel existing all import requests (remains: ", 2087c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mRunningJobMapForImport.size())); 2097c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa cancelAllImportRequest(); 2107c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 2117c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa if (mRunningJobMapForExport.size() > 0) { 2127c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa Log.i(LOG_TAG, 2137c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa String.format("Cancel existing all import requests (remains: ", 2147c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mRunningJobMapForExport.size())); 2157c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa cancelAllExportRequest(); 2167c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 2177c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa mExecutorService.shutdown(); 2187c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 2197c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa } 2207c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa 2217c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa /** 2227c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa * Removes import caches stored locally. 2237c819a1a434e02c54f6d216aa3b1a0d08cc93f50Daisuke Miyakawa */ 224aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa private void clearCache() { 225aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa Log.i(LOG_TAG, "start removing cache files if exist."); 226aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa final String[] fileLists = fileList(); 227aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa for (String fileName : fileLists) { 228aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa if (fileName.startsWith(CACHE_FILE_PREFIX)) { 229aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa // We don't want to keep all the caches so we remove cache files old enough. 230aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa // TODO: Ideally we should ask VCardService whether the file is being used or 231aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa // going to be used. 232aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa final Date now = new Date(); 233aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa final File file = getFileStreamPath(fileName); 234aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa Log.i(LOG_TAG, "Remove a temporary file: " + fileName); 235aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa deleteFile(fileName); 236aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa } 237aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa } 238aba4353bcf77ba91463cfd079feec3b6c6f59c5cDaisuke Miyakawa } 239f21bf27c13dacec9b4ed74cba9046a64948e97fbDaisuke Miyakawa} 240