Home | History | Annotate | Download | only in sip
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.services.telephony.sip;
     18 
     19 import com.android.internal.os.AtomicFile;
     20 
     21 import android.content.Context;
     22 import android.net.sip.SipProfile;
     23 import android.text.TextUtils;
     24 import android.util.Log;
     25 
     26 import java.io.File;
     27 import java.io.FileOutputStream;
     28 import java.io.IOException;
     29 import java.io.ObjectInputStream;
     30 import java.io.ObjectOutputStream;
     31 import java.util.ArrayList;
     32 import java.util.Collections;
     33 import java.util.List;
     34 
     35 /**
     36  * Utility class that helps perform operations on the SipProfile database.
     37  */
     38 class SipProfileDb {
     39     private static final String PREFIX = "[SipProfileDb] ";
     40     private static final boolean VERBOSE = false; /* STOP SHIP if true */
     41 
     42     private static final String PROFILES_DIR = "/profiles/";
     43     private static final String PROFILE_OBJ_FILE = ".pobj";
     44 
     45     private static final String SCHEME_PREFIX = "sip:";
     46 
     47     private Context mContext;
     48     private String mProfilesDirectory;
     49     private SipPreferences mSipPreferences;
     50     private int mProfilesCount = -1;
     51 
     52     public SipProfileDb(Context context) {
     53         // Sip Profile Db should always reference CE storage.
     54         mContext = context.createCredentialProtectedStorageContext();
     55         setupDatabase();
     56     }
     57 
     58     // Only should be used during migration from M->N to move database
     59     public void accessDEStorageForMigration() {
     60         mContext = mContext.createDeviceProtectedStorageContext();
     61         setupDatabase();
     62     }
     63 
     64     private void setupDatabase() {
     65         mProfilesDirectory = mContext.getFilesDir().getAbsolutePath() + PROFILES_DIR;
     66         mSipPreferences = new SipPreferences(mContext);
     67     }
     68 
     69     public void deleteProfile(SipProfile p) {
     70         synchronized(SipProfileDb.class) {
     71             deleteProfile(new File(mProfilesDirectory + p.getProfileName()));
     72             if (mProfilesCount < 0) retrieveSipProfileListInternal();
     73         }
     74     }
     75 
     76     private void deleteProfile(File file) {
     77         if (file.isDirectory()) {
     78             for (File child : file.listFiles()) deleteProfile(child);
     79         }
     80         file.delete();
     81     }
     82 
     83     public void cleanupUponMigration() {
     84         // Remove empty .../profiles/ directory
     85         File dbDir = new File(mProfilesDirectory);
     86         if(dbDir.isDirectory()) {
     87             dbDir.delete();
     88         }
     89         // Remove SharedPreferences file as well
     90         mSipPreferences.clearSharedPreferences();
     91     }
     92 
     93     public void saveProfile(SipProfile p) throws IOException {
     94         synchronized(SipProfileDb.class) {
     95             if (mProfilesCount < 0) retrieveSipProfileListInternal();
     96             File f = new File(mProfilesDirectory + p.getProfileName());
     97             if (!f.exists()) f.mkdirs();
     98             AtomicFile atomicFile = new AtomicFile(new File(f, PROFILE_OBJ_FILE));
     99             FileOutputStream fos = null;
    100             ObjectOutputStream oos = null;
    101             try {
    102                 fos = atomicFile.startWrite();
    103                 oos = new ObjectOutputStream(fos);
    104                 oos.writeObject(p);
    105                 oos.flush();
    106                 atomicFile.finishWrite(fos);
    107             } catch (IOException e) {
    108                 atomicFile.failWrite(fos);
    109                 throw e;
    110             } finally {
    111                 if (oos != null) oos.close();
    112             }
    113         }
    114     }
    115 
    116     public List<SipProfile> retrieveSipProfileList() {
    117         synchronized(SipProfileDb.class) {
    118             return retrieveSipProfileListInternal();
    119         }
    120     }
    121 
    122     private List<SipProfile> retrieveSipProfileListInternal() {
    123         List<SipProfile> sipProfileList = Collections.synchronizedList(
    124                 new ArrayList<SipProfile>());
    125 
    126         File root = new File(mProfilesDirectory);
    127         String[] dirs = root.list();
    128         if (dirs == null) return sipProfileList;
    129         for (String dir : dirs) {
    130             SipProfile p = retrieveSipProfileFromName(dir);
    131             if (p == null) continue;
    132             sipProfileList.add(p);
    133         }
    134         mProfilesCount = sipProfileList.size();
    135         return sipProfileList;
    136     }
    137 
    138     public SipProfile retrieveSipProfileFromName(String name) {
    139         if (TextUtils.isEmpty(name)) {
    140             return null;
    141         }
    142 
    143         File root = new File(mProfilesDirectory);
    144         File f = new File(new File(root, name), PROFILE_OBJ_FILE);
    145         if (f.exists()) {
    146             try {
    147                 SipProfile p = deserialize(f);
    148                 if (p != null && name.equals(p.getProfileName())) {
    149                     return p;
    150                 }
    151             } catch (IOException e) {
    152                 log("retrieveSipProfileListInternal, exception: " + e);
    153             }
    154         }
    155         return null;
    156     }
    157 
    158     private SipProfile deserialize(File profileObjectFile) throws IOException {
    159         AtomicFile atomicFile = new AtomicFile(profileObjectFile);
    160         ObjectInputStream ois = null;
    161         try {
    162             ois = new ObjectInputStream(atomicFile.openRead());
    163             SipProfile p = (SipProfile) ois.readObject();
    164             return p;
    165         } catch (ClassNotFoundException e) {
    166             log("deserialize, exception: " + e);
    167         } finally {
    168             if (ois!= null) ois.close();
    169         }
    170         return null;
    171     }
    172 
    173     private static void log(String msg) {
    174         Log.d(SipUtil.LOG_TAG, PREFIX + msg);
    175     }
    176 }
    177