/**
   * Saves the settings object fields into DB and into plain text files where applicable. The DB
   * changes will not be made persistent if saving settings to plain text files fails.
   *
   * @param s settings object
   * @return true if settings were saved successfully, false otherwise
   */
  public synchronized boolean saveSettings(PrivacySettings s) {
    boolean result = true;
    String packageName = s.getPackageName();
    //        Integer uid = s.getUid();
    //        Log.d(TAG, "saveSettings - settings save request : " + s);

    if (packageName == null || packageName.isEmpty() /* || uid == null*/) {
      Log.e(TAG, "saveSettings - either package name, UID or both is missing");
      return false;
    }

    ContentValues values = new ContentValues();
    values.put("packageName", packageName);
    //        values.put("uid", uid);
    values.put("uid", DUMMY_UID);

    values.put("deviceIdSetting", s.getDeviceIdSetting());
    values.put("deviceId", s.getDeviceId());

    values.put("line1NumberSetting", s.getLine1NumberSetting());
    values.put("line1Number", s.getLine1Number());

    values.put("locationGpsSetting", s.getLocationGpsSetting());
    values.put("locationGpsLat", s.getLocationGpsLat());
    values.put("locationGpsLon", s.getLocationGpsLon());

    values.put("locationNetworkSetting", s.getLocationNetworkSetting());
    values.put("locationNetworkLat", s.getLocationNetworkLat());
    values.put("locationNetworkLon", s.getLocationNetworkLon());

    values.put("networkInfoSetting", s.getNetworkInfoSetting());
    values.put("simInfoSetting", s.getSimInfoSetting());

    values.put("simSerialNumberSetting", s.getSimSerialNumberSetting());
    values.put("simSerialNumber", s.getSimSerialNumber());
    values.put("subscriberIdSetting", s.getSubscriberIdSetting());
    values.put("subscriberId", s.getSubscriberId());

    values.put("accountsSetting", s.getAccountsSetting());
    values.put("accountsAuthTokensSetting", s.getAccountsAuthTokensSetting());
    values.put("outgoingCallsSetting", s.getOutgoingCallsSetting());
    values.put("incomingCallsSetting", s.getIncomingCallsSetting());

    values.put("contactsSetting", s.getContactsSetting());
    values.put("calendarSetting", s.getCalendarSetting());
    values.put("mmsSetting", s.getMmsSetting());
    values.put("smsSetting", s.getSmsSetting());
    values.put("callLogSetting", s.getCallLogSetting());
    values.put("bookmarksSetting", s.getBookmarksSetting());
    values.put("systemLogsSetting", s.getSystemLogsSetting());
    values.put("notificationSetting", s.getNotificationSetting());
    values.put("intentBootCompletedSetting", s.getIntentBootCompletedSetting());
    //        values.put("externalStorageSetting", s.getExternalStorageSetting());
    //        values.put("cameraSetting", s.getCameraSetting());
    //        values.put("recordAudioSetting", s.getRecordAudioSetting());

    readingThreads++;
    SQLiteDatabase db = getWritableDatabase();
    db.beginTransaction(); // make sure this ends up in a consistent state (DB and plain text files)
    Cursor c = null;
    try {
      // save settings to the DB
      //            Log.d(TAG, "saveSettings - checking if entry exists already");
      Integer id = s.get_id();
      if (id != null) { // existing entry -> update
        //                Log.d(TAG, "saveSettings - updating existing entry");
        if (db.update(TABLE_SETTINGS, values, "_id=?", new String[] {id.toString()}) < 1) {
          throw new Exception("saveSettings - failed to update database entry");
        }

        db.delete(TABLE_ALLOWED_CONTACTS, "settings_id=?", new String[] {id.toString()});
        int[] allowedContacts = s.getAllowedContacts();
        if (allowedContacts != null) {
          ContentValues contactsValues = new ContentValues();
          for (int i = 0; i < allowedContacts.length; i++) {
            contactsValues.put("settings_id", id);
            contactsValues.put("contact_id", allowedContacts[i]);
            if (db.insert(TABLE_ALLOWED_CONTACTS, null, contactsValues) == -1)
              throw new Exception("saveSettings - failed to update database entry (contacts)");
          }
        }

      } else { // new entry -> insert if no duplicates exist
        //                Log.d(TAG, "saveSettings - new entry; verifying if duplicates exist");
        c =
            db.query(
                TABLE_SETTINGS,
                new String[] {"_id"},
                "packageName=?",
                new String[] {s.getPackageName()},
                null,
                null,
                null);

        if (c != null) {
          if (c.getCount() == 1) { // exactly one entry
            // exists -> update
            //                        Log.d(TAG, "saveSettings - updating existing entry");
            if (db.update(
                    TABLE_SETTINGS, values, "packageName=?", new String[] {s.getPackageName()})
                < 1) {
              throw new Exception("saveSettings - failed to update database entry");
            }

            if (c.moveToFirst()) {
              Integer idAlt = c.getInt(0); // id of the found duplicate entry
              db.delete(TABLE_ALLOWED_CONTACTS, "settings_id=?", new String[] {idAlt.toString()});
              int[] allowedContacts = s.getAllowedContacts();
              if (allowedContacts != null) {
                ContentValues contactsValues = new ContentValues();
                for (int i = 0; i < allowedContacts.length; i++) {
                  contactsValues.put("settings_id", idAlt);
                  contactsValues.put("contact_id", allowedContacts[i]);
                  if (db.insert(TABLE_ALLOWED_CONTACTS, null, contactsValues) == -1)
                    throw new Exception(
                        "saveSettings - failed to update database entry (contacts)");
                }
              }
            }
          } else if (c.getCount() == 0) { // no entries -> insert
            //                        Log.d(TAG, "saveSettings - inserting new entry");
            long rowId = db.insert(TABLE_SETTINGS, null, values);
            if (rowId == -1) {
              throw new Exception("saveSettings - failed to insert new record into DB");
            }

            db.delete(TABLE_ALLOWED_CONTACTS, "settings_id=?", new String[] {Long.toString(rowId)});
            int[] allowedContacts = s.getAllowedContacts();
            if (allowedContacts != null) {
              ContentValues contactsValues = new ContentValues();
              for (int i = 0; i < allowedContacts.length; i++) {
                contactsValues.put("settings_id", rowId);
                contactsValues.put("contact_id", allowedContacts[i]);
                if (db.insert(TABLE_ALLOWED_CONTACTS, null, contactsValues) == -1)
                  throw new Exception("saveSettings - failed to update database entry (contacts)");
              }
            }
          } else { // something went totally wrong and there are multiple entries for same
                   // identifier
            result = false;
            throw new Exception("saveSettings - duplicate entries in the privacy.db");
          }
        } else {
          result = false;
          // jump to catch block to avoid marking transaction as successful
          throw new Exception("saveSettings - cursor is null, database access failed");
        }
      }

      // save settings to plain text file (for access from core libraries)
      //            Log.d(TAG, "saveSettings - saving to plain text file");
      //            File settingsUidDir = new File("/data/system/privacy/" + packageName + "/" + uid
      // + "/");
      File settingsPackageDir = new File("/data/system/privacy/" + packageName + "/");
      File systemLogsSettingFile =
          new File("/data/system/privacy/" + packageName + "/" + "/systemLogsSetting");
      try {
        // create all parent directories on the file path
        //                settingsUidDir.mkdirs();
        // make the directory readable (requires it to be executable as well)
        //                settingsUidDir.setReadable(true, false);
        //                settingsUidDir.setExecutable(true, false);
        // make the parent directory readable (requires it to be executable as well)
        settingsPackageDir.mkdirs();
        settingsPackageDir.setReadable(true, false);
        settingsPackageDir.setExecutable(true, false);
        // create the setting files and make them readable
        systemLogsSettingFile.createNewFile();
        systemLogsSettingFile.setReadable(true, false);
        // write settings to files
        //                Log.d(TAG, "saveSettings - writing to file");
        OutputStreamWriter writer =
            new OutputStreamWriter(new FileOutputStream(systemLogsSettingFile));
        writer.append(s.getSystemLogsSetting() + "");
        writer.flush();
        writer.close();
      } catch (IOException e) {
        result = false;
        // jump to catch block to avoid marking transaction as successful
        throw new Exception("saveSettings - could not write settings to file", e);
      }
      // mark DB transaction successful (commit the changes)
      db.setTransactionSuccessful();
      //            Log.d(TAG, "saveSettings - completing transaction");
    } catch (Exception e) {
      result = false;
      //            Log.d(TAG, "saveSettings - could not save settings", e);
    } finally {
      db.endTransaction();
      if (c != null) c.close();
      synchronized (readingThreads) {
        readingThreads--;
        // only close DB if no other threads are reading
        if (readingThreads == 0 && db != null && db.isOpen()) {
          db.close();
        }
      }
    }

    return result;
  }
 @Override
 public void onClick(View v) {
   switch (v.getId()) {
     case R.id.id_offocial_id_layout:
       Intent intent = new Intent(MoreScreen.this, SharedIDScreen.class);
       startActivity(intent);
       break;
     case R.id.id_memberstats_layout:
       intent = new Intent(MoreScreen.this, MemberStatsScreen.class);
       startActivity(intent);
       break;
     case R.id.id_data_usage_layout:
       {
         intent = new Intent(this, DataUsageSetting.class);
         startActivity(intent);
         break;
       }
     case R.id.id_chat_layout:
       intent = new Intent(this, ChatBackupScreen.class);
       startActivity(intent);
       break;
     case R.id.id_open_console:
       {
         try {
           Intent intentOpenWeb =
               new Intent(
                   Intent.ACTION_VIEW,
                   Uri.parse(getResources().getString(R.string.text_activate_web_console_link)));
           startActivity(intentOpenWeb);
         } catch (Exception e) {
           Toast.makeText(this, "Not supported", Toast.LENGTH_SHORT).show();
         }
         break;
       }
     case R.id.id_configure_console_pass:
       intent = new Intent(this, GenerateConsolePasswordActivity.class);
       startActivity(intent);
       break;
     case R.id.id_privacy_layout:
       PrivacySettings.start(this);
       // showPrivacyOptionsDialog(true);
       break;
     case R.id.id_snooze_layout:
       //                boolean expired =
       // sharedPrefManager.isSnoozeExpired(sharedPrefManager.getUserDomain());
       //                int index =
       // sharedPrefManager.getSnoozeIndex(sharedPrefManager.getUserDomain());
       //                if(expired &&
       // sharedPrefManager.getSnoozeIndex(sharedPrefManager.getUserDomain()) == 0) {
       //                    showSnoozeDialog();
       //                }else{
       //                    showUpdateDialog("", "Un-mute?");
       //                }
       showSnoozeDialog();
       break;
       //		case R.id.id_member_stats_layout:
       //			Intent intent = new Intent(this, MemberStatsScreen.class);
       //			startActivity(intent);
       //			break;
     case R.id.id_supergroup_profile:
       intent = new Intent(this, SuperGroupProfileActivity.class);
       startActivity(intent);
       break;
     case R.id.id_manage_members_layout:
       intent = new Intent(this, EsiaChatContactsScreen.class);
       intent.putExtra(Constants.CHAT_TYPE, Constants.MEMBER_DELETE);
       intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
       intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       startActivityForResult(intent, 105);
       break;
     case R.id.id_feedback_layout:
       Intent mailIntent = new Intent(android.content.Intent.ACTION_SEND);
       mailIntent.setType("text/plain");
       mailIntent.putExtra(Intent.EXTRA_SUBJECT, "Feedback");
       mailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"*****@*****.**"});
       mailIntent.putExtra(Intent.EXTRA_TEXT, Utilities.getSupportParameters(this));
       final PackageManager pm = getPackageManager();
       final List<ResolveInfo> matches = pm.queryIntentActivities(mailIntent, 0);
       ResolveInfo best = null;
       for (final ResolveInfo info : matches)
         if (info.activityInfo.packageName.endsWith(".gm")
             || info.activityInfo.name.toLowerCase().contains("gmail")) best = info;
       if (best != null)
         mailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
       startActivity(mailIntent);
       break;
     case R.id.id_profile_layout:
       intent = new Intent(this, ProfileScreen.class);
       intent.putExtra(Constants.PROFILE_UPDATE, true);
       startActivity(intent);
       //			finish();
       break;
     case R.id.id_advanced_settings:
       showAdvancedSettingsDialog();
       //			intent = new Intent(this, CreateSharedIDActivity.class);
       //			intent = new Intent(this, SharedIDScreen.class);
       //			startActivity(intent);
       break;
       //		case R.id.id_setting_layout:
       //			Toast.makeText(getActivity(), getString(R.string.coming_soon_lbl),
       // Toast.LENGTH_SHORT).show();
       //			break;
       //		case R.id.id_account_layout:
       //			intent = new Intent(getActivity(), AccountScreen.class);
       //			startActivity(intent);
       //			break;
       //		case R.id.id_invite_layout:
       //			//do invite here
       //			try {
       //				String text =
       // SuperChatApplication.context.getResources().getString(R.string.invite_text);
       //				Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
       //				shareIntent.setType("text/plain");
       //				shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, text);
       //				startActivity(Intent.createChooser(shareIntent,
       // SuperChatApplication.context.getString(R.string.invite)));
       //			} catch (Exception e) {
       //				//				        Toast.makeText(KainatInviteSelection.this, "Facebook not Installed",
       // Toast.LENGTH_SHORT).show();
       //			}
       //			intent = new Intent(this, BulkInvitationScreen.class);
       //			startActivity(intent);
       //			break;
       //		case R.id.id_help_item:
       //			intent = new Intent(getActivity(), HelpScreen.class);
       //			startActivity(intent);
       //			break;
     case R.id.id_chat_settings:
       showPrivacyOptionsDialog(false);
       intent = new Intent(this, PrivacyChatSettings.class);
       startActivity(intent);
       break;
     case R.id.id_call_settings:
       showPrivacyOptionsDialog(false);
       intent = new Intent(this, PrivacyCallSettings.class);
       startActivity(intent);
       break;
     case R.id.id_block_list: // id_block_list_layout:
       showPrivacyOptionsDialog(false);
       intent = new Intent(this, BlockListScreen.class);
       startActivity(intent);
       break;
     case R.id.id_about_us:
       intent = new Intent(this, AboutScreen.class);
       startActivity(intent);
       break;
     case R.id.id_checkupdate_layout:
       if (Build.VERSION.SDK_INT >= 11)
         new GetVersionTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
       else new GetVersionTask().execute();
       break;
   }
 }
  public PrivacySettings getSettings(String packageName, boolean forceCloseDB) {
    PrivacySettings s = null;

    if (packageName == null) {
      Log.e(TAG, "getSettings - insufficient application identifier - package name is required");
      return s;
    }

    // indicate that the DB is being read to prevent closing by other threads
    readingThreads++;
    //        Log.d(TAG, "getSettings - settings request for package: " + packageName + "
    // readingThreads: " + readingThreads);

    SQLiteDatabase db;
    try {
      db = getReadableDatabase();
    } catch (SQLiteException e) {
      Log.e(TAG, "getSettings - database could not be opened", e);
      readingThreads--;
      return s;
    }

    Cursor c = null;

    try {
      c =
          query(
              db,
              TABLE_SETTINGS,
              DATABASE_FIELDS,
              "packageName=?",
              new String[] {packageName},
              null,
              null,
              null,
              null);

      if (c != null && c.moveToFirst()) {
        s =
            new PrivacySettings(
                c.getInt(0),
                c.getString(1),
                c.getInt(2),
                (byte) c.getShort(3),
                c.getString(4),
                (byte) c.getShort(5),
                c.getString(6),
                (byte) c.getShort(7),
                c.getString(8),
                c.getString(9),
                (byte) c.getShort(10),
                c.getString(11),
                c.getString(12),
                (byte) c.getShort(13),
                (byte) c.getShort(14),
                (byte) c.getShort(15),
                c.getString(16),
                (byte) c.getShort(17),
                c.getString(18),
                (byte) c.getShort(19),
                (byte) c.getShort(20),
                (byte) c.getShort(21),
                (byte) c.getShort(22),
                (byte) c.getShort(23),
                (byte) c.getShort(24),
                (byte) c.getShort(25),
                (byte) c.getShort(26),
                (byte) c.getShort(27),
                (byte) c.getShort(28),
                (byte) c.getShort(29),
                (byte) c.getShort(30),
                (byte) c.getShort(31),
                (byte) c.getShort(32),
                (byte) c.getShort(33),
                (byte) c.getShort(34),
                null);

        // get allowed contacts IDs if necessary
        //                Log.d(TAG, "getSettings - looking for allowed contacts for " +
        // s.get_id());
        //                c = query(db, TABLE_ALLOWED_CONTACTS, null,
        //                        "settings_id=?", new String[] { Integer.toString(s.get_id()) },
        // null, null, null, null);
        c =
            rawQuery(
                db,
                "SELECT * FROM allowed_contacts WHERE settings_id="
                    + Integer.toString(s.get_id())
                    + ";");

        if (c != null && c.getCount() > 0) {
          //                    Log.d(TAG, "getSettings - found allowed contacts");
          int[] allowedContacts = new int[c.getCount()];
          while (c.moveToNext()) allowedContacts[c.getPosition()] = c.getInt(1);
          s.setAllowedContacts(allowedContacts);
        }
        //                    Log.d(TAG, "getSettings - found settings entry for package: " +
        // packageName + " UID: " + uid);
      }
      //            else {
      //                Log.e(TAG, "getSettings - no settings found for package: " + packageName);
      //            }
    } catch (Exception e) {
      Log.e(TAG, "getSettings - failed to get settings for package: " + packageName, e);
      e.printStackTrace();
      if (c != null) c.close();
    } finally {
      if (c != null) c.close();
      //            if (forceCloseDB && db != null && db.isOpen()) {
      //                db.close();
      //            } else {
      synchronized (readingThreads) {
        readingThreads--;
        // only close DB if no other threads are reading
        if (readingThreads == 0 && db != null && db.isOpen()) {
          db.close();
        }
      }
      //            }
    }

    //        Log.d(TAG, "getSettings - returning settings: " + s);
    return s;
  }