diff options
Diffstat (limited to 'src/com/android')
94 files changed, 2986 insertions, 2013 deletions
diff --git a/src/com/android/display/IPPService.aidl b/src/com/android/display/IPPService.aidl deleted file mode 100644 index c934efe..0000000 --- a/src/com/android/display/IPPService.aidl +++ /dev/null @@ -1,7 +0,0 @@ -package com.android.display; -interface IPPService { - boolean startPP(); - boolean stopPP(); - boolean updateHSIC(int h, int s, int i, int c); - boolean getPPStatus(); -} diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java index 2ed7438..3d744d6 100644 --- a/src/com/android/settings/ApnEditor.java +++ b/src/com/android/settings/ApnEditor.java @@ -281,7 +281,7 @@ public class ApnEditor extends InstrumentedPreferenceActivity private void fillUi() { if (mFirstTime) { mFirstTime = false; - String numeric = mTelephonyManager.getSimOperator(mSubId); + String numeric = mTelephonyManager.getIccOperatorNumericForData(mSubId); // Fill in all the values from the db in both text editor and summary mName.setText(mCursor.getString(NAME_INDEX)); mApn.setText(mCursor.getString(APN_INDEX)); @@ -489,7 +489,7 @@ public class ApnEditor extends InstrumentedPreferenceActivity if (values[mvnoIndex].equals("SPN")) { mMvnoMatchData.setText(mTelephonyManager.getSimOperatorName()); } else if (values[mvnoIndex].equals("IMSI")) { - String numeric = mTelephonyManager.getSimOperator(mSubId); + String numeric = mTelephonyManager.getIccOperatorNumericForData(mSubId); mMvnoMatchData.setText(numeric + "x"); } else if (values[mvnoIndex].equals("GID")) { mMvnoMatchData.setText(mTelephonyManager.getGroupIdLevel1()); diff --git a/src/com/android/settings/ApnSettings.java b/src/com/android/settings/ApnSettings.java index 697094a..b36ab1c 100644 --- a/src/com/android/settings/ApnSettings.java +++ b/src/com/android/settings/ApnSettings.java @@ -72,8 +72,12 @@ public class ApnSettings extends SettingsPreferenceFragment implements public static final String PREFERRED_APN_URI = "content://telephony/carriers/preferapn"; + public static final Uri PREFERRED_MSIM_APN_URI = + Uri.parse("content://telephony/carriers/preferapn/subIdImsi"); + public static final String APN_ID = "apn_id"; public static final String SUB_ID = "sub_id"; + public static final String EXTRA_IMSI = "imsi"; public static final String MVNO_TYPE = "mvno_type"; public static final String MVNO_MATCH_DATA = "mvno_match_data"; @@ -117,6 +121,8 @@ public class ApnSettings extends SettingsPreferenceFragment implements private boolean mHideImsApn; private boolean mAllowAddingApns; + private String mImsi; + private final BroadcastReceiver mMobileStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -157,6 +163,8 @@ public class ApnSettings extends SettingsPreferenceFragment implements final int subId = activity.getIntent().getIntExtra(SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + mImsi = activity.getIntent().getStringExtra(EXTRA_IMSI); + mUm = (UserManager) getSystemService(Context.USER_SERVICE); mMobileStateFilter = new IntentFilter( @@ -408,19 +416,35 @@ public class ApnSettings extends SettingsPreferenceFragment implements ContentValues values = new ContentValues(); values.put(APN_ID, mSelectedKey); - resolver.update(PREFERAPN_URI, values, null, null); + if (TelephonyManager.getDefault().getPhoneCount() > 1 && mImsi != null) { + Uri qUri = Uri.withAppendedPath(PREFERRED_MSIM_APN_URI, + String.valueOf(mSubscriptionInfo.getSubscriptionId())); + qUri = Uri.withAppendedPath(qUri, mImsi); + resolver.update(qUri, values, null, null); + } else { + resolver.update(PREFERAPN_URI, values, null, null); + } } private String getSelectedApnKey() { String key = null; - Cursor cursor = getContentResolver().query(PREFERAPN_URI, new String[] {"_id"}, - null, null, Telephony.Carriers.DEFAULT_SORT_ORDER); - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - key = cursor.getString(ID_INDEX); + Uri uri; + if (TelephonyManager.getDefault().getPhoneCount() > 1 && mImsi != null + && mSubscriptionInfo != null) { + uri = Uri.withAppendedPath(PREFERRED_MSIM_APN_URI, + String.valueOf(mSubscriptionInfo.getSubscriptionId())); + uri = Uri.withAppendedPath(uri, mImsi); + } else { + uri = PREFERAPN_URI; + } + try (Cursor cursor = getContentResolver().query(uri, new String[] {"_id"}, + null, null, Telephony.Carriers.DEFAULT_SORT_ORDER)) { + if (cursor != null && cursor.getCount() > 0) { + cursor.moveToFirst(); + key = cursor.getString(ID_INDEX); + } } - cursor.close(); return key; } diff --git a/src/com/android/settings/BugreportPreference.java b/src/com/android/settings/BugreportPreference.java index ba58ef4..ca4fa1d 100644 --- a/src/com/android/settings/BugreportPreference.java +++ b/src/com/android/settings/BugreportPreference.java @@ -16,11 +16,12 @@ package com.android.settings; +import android.app.ActivityManagerNative; import android.app.AlertDialog.Builder; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; -import android.os.SystemProperties; +import android.os.RemoteException; import android.preference.DialogPreference; import android.util.AttributeSet; import android.view.View; @@ -55,7 +56,11 @@ public class BugreportPreference extends DialogPreference { @Override public void onClick(DialogInterface dialog, int which) { if (which == DialogInterface.BUTTON_POSITIVE) { - SystemProperties.set("ctl.start", "bugreport"); + try { + ActivityManagerNative.getDefault().requestBugReport(); + } catch (RemoteException e) { + // ignore + } } } } diff --git a/src/com/android/settings/ButtonSettings.java b/src/com/android/settings/ButtonSettings.java index 09c9b7d..109d7dc 100644 --- a/src/com/android/settings/ButtonSettings.java +++ b/src/com/android/settings/ButtonSettings.java @@ -407,8 +407,8 @@ public class ButtonSettings extends SettingsPreferenceFragment implements try { // Only show the navigation bar category on devices that have a navigation bar // unless we are forcing it via development settings - boolean forceNavbar = CMSettings.Secure.getInt(getContentResolver(), - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0) == 1; + boolean forceNavbar = CMSettings.Global.getInt(getContentResolver(), + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0) == 1; boolean hasNavBar = WindowManagerGlobal.getWindowManagerService().hasNavigationBar() || forceNavbar; @@ -628,13 +628,13 @@ public class ButtonSettings extends SettingsPreferenceFragment implements } private static void writeDisableNavkeysOption(Context context, boolean enabled) { - CMSettings.Secure.putInt(context.getContentResolver(), - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, enabled ? 1 : 0); + CMSettings.Global.putInt(context.getContentResolver(), + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, enabled ? 1 : 0); } private void updateDisableNavkeysOption() { - boolean enabled = CMSettings.Secure.getInt(getActivity().getContentResolver(), - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0) != 0; + boolean enabled = CMSettings.Global.getInt(getActivity().getContentResolver(), + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0) != 0; mDisableNavigationKeys.setChecked(enabled); } @@ -687,8 +687,8 @@ public class ButtonSettings extends SettingsPreferenceFragment implements return; } - writeDisableNavkeysOption(context, CMSettings.Secure.getInt(context.getContentResolver(), - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0) != 0); + writeDisableNavkeysOption(context, CMSettings.Global.getInt(context.getContentResolver(), + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0) != 0); } diff --git a/src/com/android/settings/CarrierSelection.java b/src/com/android/settings/CarrierSelection.java new file mode 100644 index 0000000..1044380 --- /dev/null +++ b/src/com/android/settings/CarrierSelection.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014-2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Intent; +import android.os.Bundle; + +public class CarrierSelection extends Activity { + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setComponent(new ComponentName("com.android.phone", + "com.android.phone.NetworkSetting")); + startActivity(intent); + finish(); + } +} diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java index c85e604..5dd6b9c 100644 --- a/src/com/android/settings/ChooseLockPattern.java +++ b/src/com/android/settings/ChooseLockPattern.java @@ -703,7 +703,7 @@ public class ChooseLockPattern extends SettingsActivity { protected Intent saveAndVerifyInBackground() { Intent result = null; final int userId = UserHandle.myUserId(); - mUtils.setLockPatternSize(mPatternSize); + mUtils.setLockPatternSize(mPatternSize, userId); mUtils.saveLockPattern(mChosenPattern, mCurrentPattern, userId); if (mHasChallenge) { diff --git a/src/com/android/settings/ChooseLockPatternSize.java b/src/com/android/settings/ChooseLockPatternSize.java index 59b0644..b6f17f1 100644 --- a/src/com/android/settings/ChooseLockPatternSize.java +++ b/src/com/android/settings/ChooseLockPatternSize.java @@ -92,8 +92,13 @@ public class ChooseLockPatternSize extends PreferenceActivity { originatingIntent.getLongExtra( ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0)); } + // Forward the Encryption interstitial required password selection + if (originatingIntent.hasExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD)) { + intent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, originatingIntent + .getBooleanExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true)); + } intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); - startActivity(intent); + startActivity(intent); finish(); return true; diff --git a/src/com/android/settings/CmRadioInfo.java b/src/com/android/settings/CmRadioInfo.java new file mode 100644 index 0000000..112f4d8 --- /dev/null +++ b/src/com/android/settings/CmRadioInfo.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings; + +import android.app.Activity; +import android.os.Bundle; +import android.os.SystemProperties; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; + +public class CmRadioInfo extends Activity { + private final String TAG = "CmRadioInfo"; + + private Button mbnAutoLoadButton; + private Button volteAvailOvrButton; + private Button vtAvailOvrButton; + private Button wfcAvailOvrButton; + private Button adbRadioLog; + private Button diagLog; + + static final String PROPERTY_SW_MBN_UPDATE = "persist.radio.sw_mbn_update"; + static final String PROPERTY_SW_MBN_VOLTE = "persist.radio.sw_mbn_volte"; + static final String PROPERTY_VOLTE_AVAIL_OVR = "persist.dbg.volte_avail_ovr"; + static final String PROPERTY_VT_AVAIL_OVR = "persist.dbg.vt_avail_ovr"; + static final String PROPERTY_DATA_IWLAN_ENABLE = "persist.data.iwlan.enable"; + static final String PROPERTY_WFC_AVAIL_OVR = "persist.dbg.wfc_avail_ovr"; + static final String PROPERTY_ADB_LOG_ON = "persist.radio.adb_log_on"; + static final String PROPERTY_DIAG_LOG_ON = "persist.radio.diag_log_on"; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + setContentView(R.layout.cm_radio_info); + + mbnAutoLoadButton = (Button) findViewById(R.id.mbn_auto_load); + mbnAutoLoadButton.setOnClickListener(mMbnAutoLoadHandler); + + volteAvailOvrButton = (Button) findViewById(R.id.volte_avail_ovr); + volteAvailOvrButton.setOnClickListener(mVolteAvailOvrHandler); + + vtAvailOvrButton = (Button) findViewById(R.id.vt_avail_ovr); + vtAvailOvrButton.setOnClickListener(mVtAvailOvrHandler); + + wfcAvailOvrButton = (Button) findViewById(R.id.wfc_avail_ovr); + wfcAvailOvrButton.setOnClickListener(mWfcAvailOvrHandler); + + adbRadioLog = (Button) findViewById(R.id.adb_radio_log); + adbRadioLog.setOnClickListener(mAdbRadioLogHandler); + + diagLog = (Button) findViewById(R.id.diag_log); + diagLog.setOnClickListener(mDiagLogHandler); + } + + @Override + protected void onResume() { + super.onResume(); + + updateMbnAutoLoadState(); + updateVolteAvailOvrState(); + updateVtAvailOvrState(); + updateWfcAvailOvrState(); + updateAdbRadioLogState(); + updateDiagLogState(); + + log("onResume: update cm radio info"); + } + + @Override + public void onPause() { + super.onPause(); + + log("onPause: cm radio info"); + } + + OnClickListener mMbnAutoLoadHandler = new OnClickListener() { + @Override + public void onClick(View v) { + SystemProperties.set(PROPERTY_SW_MBN_UPDATE, (isMbnAutoLoad() ? "0" : "1")); + updateMbnAutoLoadState(); + } + }; + + private boolean isMbnAutoLoad() { + return SystemProperties.getBoolean(PROPERTY_SW_MBN_UPDATE, false); + } + + private void updateMbnAutoLoadState() { + log("updateMbnAutoLoadState isMbnAutoLoad()=" + isMbnAutoLoad()); + String buttonText = isMbnAutoLoad() ? + getString(R.string.cm_radio_info_mbn_auto_load_on_label) : + getString(R.string.cm_radio_info_mbn_auto_load_off_label); + mbnAutoLoadButton.setText(buttonText); + } + + OnClickListener mVolteAvailOvrHandler = new OnClickListener() { + @Override + public void onClick(View v) { + SystemProperties.set(PROPERTY_SW_MBN_VOLTE, (isVolteAvailOvr() ? "0" : "1")); + SystemProperties.set(PROPERTY_VOLTE_AVAIL_OVR, (isVolteAvailOvr() ? "0" : "1")); + updateVolteAvailOvrState(); + } + }; + + private boolean isVolteAvailOvr() { + return SystemProperties.getBoolean(PROPERTY_VOLTE_AVAIL_OVR, false); + } + + private void updateVolteAvailOvrState() { + log("updateVolteAvailOvrState isVolteAvailOvr()=" + isVolteAvailOvr()); + String buttonText = isVolteAvailOvr() ? + getString(R.string.cm_radio_info_volte_avail_ovr_on_label) : + getString(R.string.cm_radio_info_volte_avail_ovr_off_label); + volteAvailOvrButton.setText(buttonText); + } + + OnClickListener mVtAvailOvrHandler = new OnClickListener() { + @Override + public void onClick(View v) { + SystemProperties.set(PROPERTY_VT_AVAIL_OVR, (isVtAvailOvr() ? "0" : "1")); + updateVtAvailOvrState(); + } + }; + + private boolean isVtAvailOvr() { + return SystemProperties.getBoolean(PROPERTY_VT_AVAIL_OVR, false); + } + + private void updateVtAvailOvrState() { + log("updateVtAvailOvrState isVtAvailOvr()=" + isVtAvailOvr()); + String buttonText = isVtAvailOvr() ? + getString(R.string.cm_radio_info_vt_avail_ovr_on_label) : + getString(R.string.cm_radio_info_vt_avail_ovr_off_label); + vtAvailOvrButton.setText(buttonText); + } + + OnClickListener mWfcAvailOvrHandler = new OnClickListener() { + @Override + public void onClick(View v) { + SystemProperties.set(PROPERTY_DATA_IWLAN_ENABLE, (isWfcAvailOvr() ? "false" : "true")); + SystemProperties.set(PROPERTY_WFC_AVAIL_OVR, (isWfcAvailOvr() ? "0" : "1")); + updateWfcAvailOvrState(); + } + }; + + private boolean isWfcAvailOvr() { + return SystemProperties.getBoolean(PROPERTY_WFC_AVAIL_OVR, false); + } + + private void updateWfcAvailOvrState() { + log("updateWfcAvailOvrState isWfcAvailOvr()=" + isWfcAvailOvr()); + String buttonText = isWfcAvailOvr() ? + getString(R.string.cm_radio_info_wfc_avail_ovr_on_label) : + getString(R.string.cm_radio_info_wfc_avail_ovr_off_label); + wfcAvailOvrButton.setText(buttonText); + } + + OnClickListener mAdbRadioLogHandler = new OnClickListener() { + @Override + public void onClick(View v) { + SystemProperties.set(PROPERTY_ADB_LOG_ON, (isAdbRadioLog() ? "0" : "1")); + updateAdbRadioLogState(); + } + }; + + private boolean isAdbRadioLog() { + return SystemProperties.getBoolean(PROPERTY_ADB_LOG_ON, false); + } + + private void updateAdbRadioLogState() { + log("updateAdbRadioLogState isAdbRadioLog()=" + isAdbRadioLog()); + String buttonText = isAdbRadioLog() ? + getString(R.string.cm_radio_info_adb_log_on_label) : + getString(R.string.cm_radio_info_adb_log_off_label); + adbRadioLog.setText(buttonText); + } + + OnClickListener mDiagLogHandler = new OnClickListener() { + @Override + public void onClick(View v) { + SystemProperties.set(PROPERTY_DIAG_LOG_ON, (isDiagLog() ? "0" : "1")); + updateDiagLogState(); + } + }; + + private boolean isDiagLog() { + return SystemProperties.getBoolean(PROPERTY_DIAG_LOG_ON, false); + } + + private void updateDiagLogState() { + log("updateDiagLogState isDiagLog()=" + isDiagLog()); + String buttonText = isDiagLog() ? + getString(R.string.cm_radio_info_diag_log_on_label) : + getString(R.string.cm_radio_info_diag_log_off_label); + diagLog.setText(buttonText); + } + + private void log(String s) { + Log.d(TAG, "[Phone] " + s); + } +} diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java b/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java index d9af800..2d78de2 100644 --- a/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java +++ b/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java @@ -92,11 +92,17 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi } public void prepareEnterAnimation() { - getFragment().prepareEnterAnimation(); + final ConfirmDeviceCredentialBaseFragment f = getFragment(); + if (f != null) { + f.prepareEnterAnimation(); + } } public void startEnterAnimation() { - getFragment().startEnterAnimation(); + final ConfirmDeviceCredentialBaseFragment f = getFragment(); + if (f != null) { + f.startEnterAnimation(); + } } /** diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java index a402b4b..2e74691 100644 --- a/src/com/android/settings/ConfirmLockPattern.java +++ b/src/com/android/settings/ConfirmLockPattern.java @@ -146,7 +146,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { mLockPatternUtils.isTactileFeedbackEnabled()); mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled( mEffectiveUserId)); - mLockPatternView.setLockPatternSize(mLockPatternUtils.getLockPatternSize()); + mLockPatternView.setLockPatternSize(mLockPatternUtils.getLockPatternSize(mEffectiveUserId)); mLockPatternView.setOnPatternListener(mConfirmExistingLockPatternListener); updateStage(Stage.NeedToUnlock); @@ -459,7 +459,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, StorageManager.CRYPT_TYPE_PATTERN); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, - mLockPatternUtils.patternToString(pattern)); + mLockPatternUtils.patternToString(pattern, localEffectiveUserId)); } mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs, localEffectiveUserId); diff --git a/src/com/android/settings/CustomScreenColor.java b/src/com/android/settings/CustomScreenColor.java deleted file mode 100644 index 2d6c7c2..0000000 --- a/src/com/android/settings/CustomScreenColor.java +++ /dev/null @@ -1,721 +0,0 @@ -/* - Copyright (c) 2014, The Linux Foundation. All Rights Reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package com.android.settings; - -import android.app.ActionBar; -import android.app.Activity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.drawable.BitmapDrawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; -import android.view.Gravity; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ListView; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.PopupMenu; -import android.widget.PopupMenu.OnMenuItemClickListener; -import android.widget.RelativeLayout; -import android.widget.SeekBar; -import android.widget.TextView; -import android.widget.PopupWindow; - -import com.android.display.IPPService; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -public class CustomScreenColor extends Activity implements SeekBar.OnSeekBarChangeListener, - View.OnClickListener { - private final static String TAG = "CustomScreenColor"; - - private static final int RESTORE_DEFAULT_PREVIEW = 0; - private static final int SELECT_NEW_FILE_ITEM = 1; - private static final int SELECT_FILE_ITEM = 2; - private static final int RESET = 3; - private static final int SELECT_FILE_GROUP1 = 0; - private static final int SELECT_FILE_GROUP2 = 1; - private static final int SELECT_FILE_ORDER = 0; - private static final int REQUEST_SELECT_FILE = 100; - private static final String IMAGE_UNSPECIFIED = "image/*"; - private static final String PREVIEW_STRING_KEY = "screencolor_preview_key"; - private static final String PREVIEW_STRING_NAME = "screencolor_preview_name"; - private static final String COLOR_HUE = "hue"; - private static final String COLOR_SATURATION = "saturation"; - private static final String COLOR_INTENSITY = "intensity"; - private static final String COLOR_CONTRAST = "contrast"; - - private static final String KEY_ASPECT_X = "aspectX"; - private static final String KEY_ASPECT_Y = "aspectY"; - private static final String KEY_SPOTLIGHT_X = "spotlightX"; - private static final String KEY_SPOTLIGHT_Y = "spotlightY"; - private static final String KEY_FROME_SCREENCOLOR = "fromScreenColor"; - - private ImageView mImageView; - private RelativeLayout mRLayout; - private LinearLayout mScreenColorLayout; - private SeekBar mHBar, mSBar, mCBar, mIBar; - private TextView mHTv, mSTv, mCTv, mITv; - private ImageView mReduceH, mIncreaseH, mReduceS, mIncreaseS, mReduceC, mIncreaseC, mReduceI, - mIncreaseI, mUpdown, mMore; - private Button mCancelBtn, mSaveBtn, mPreviousBtn, mNewBtn; - private boolean canRestorePreview; - private int mHueValue = 0; - private int mSaturationValue = 0; - private int mIntensityValue = 0; - private int mContrastValue = 0; - - private int mMinHueValue = 0; - private int mMaxHueValue = 0; - private int mDefaultHueValue = 0; - private int mMinSaturationValue = 0; - private int mMaxSaturationValue = 0; - private int mDefaultSaturationValue = 0; - private int mMinIntensityValue = 0; - private int mMaxIntensityValue = 0; - private int mDefaultIntensityValue = 0; - private int mMinContrastValue = 0; - private int mMaxContrastValue = 0; - private int mDefaultContrastValue = 0; - - /** - * It is used to update the screen's hue, saturation, contrast, and intensity. - */ - IPPService mPPService = null; - PPServiceConnection mPPServiceConn = null; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - initPPService(); - getWindow().requestFeature(Window.FEATURE_ACTION_BAR); - setContentView(R.layout.custom_screencolor); - initView(); - restoreSavedHSCI(true); - } - - @Override - protected void onResume() { - super.onResume(); - } - - @Override - protected void onPause() { - super.onPause(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - unbindService(mPPServiceConn); - } - - private void initView() { - ActionBar actionBar = getActionBar(); - actionBar.setDisplayHomeAsUpEnabled(true); - - mMinHueValue = getResources().getInteger(R.integer.minimum_hue_value); - mMaxHueValue = getResources().getInteger(R.integer.maximum_hue_value); - mDefaultHueValue = getResources().getInteger(R.integer.default_hue_value); - mMinSaturationValue = getResources().getInteger(R.integer.minimum_saturation_value); - mMaxSaturationValue = getResources().getInteger(R.integer.maximum_saturation_value); - mDefaultSaturationValue = getResources().getInteger(R.integer.default_saturation_value); - mMinIntensityValue = getResources().getInteger(R.integer.minimum_intensity_value); - mMaxIntensityValue = getResources().getInteger(R.integer.maximum_intensity_value); - mDefaultIntensityValue = getResources().getInteger(R.integer.default_intensity_value); - mMinContrastValue = getResources().getInteger(R.integer.minimum_contrast_value); - mMaxContrastValue = getResources().getInteger(R.integer.maximum_contrast_value); - mDefaultContrastValue = getResources().getInteger(R.integer.default_contrast_value); - - mRLayout = (RelativeLayout) findViewById(R.id.background_preview); - String previewContent = getScreenColorPreviewKey(); - if ("".equals(previewContent)) { - resotreBackgroundByDefault(); - } else { - Uri previewUri = Uri.parse(previewContent); - setBackgroundByUri(previewUri); - } - - mScreenColorLayout = (LinearLayout) findViewById(R.id.screencolor_control); - mScreenColorLayout.setBackgroundColor(R.color.screencolor_background); - mScreenColorLayout.setOnClickListener(this); - - mHBar = (SeekBar) findViewById(R.id.hcontrol); - mHBar.setMax(mMaxHueValue); - mHBar.setOnSeekBarChangeListener(this); - mSBar = (SeekBar) findViewById(R.id.scontrol); - mSBar.setMax(mMaxSaturationValue); - mSBar.setOnSeekBarChangeListener(this); - mIBar = (SeekBar) findViewById(R.id.icontrol); - mIBar.setMax(mMaxIntensityValue); - mIBar.setOnSeekBarChangeListener(this); - mCBar = (SeekBar) findViewById(R.id.ccontrol); - mCBar.setMax(mMaxContrastValue); - mCBar.setOnSeekBarChangeListener(this); - - mHTv = (TextView) findViewById(R.id.hue); - mHTv.setText(getString(R.string.hue_str, mHBar.getProgress())); - mSTv = (TextView) findViewById(R.id.saturation); - mSTv.setText(getString(R.string.saturation_str, mSBar.getProgress())); - mITv = (TextView) findViewById(R.id.intensity); - mITv.setText(getString(R.string.intensity_str, mIBar.getProgress())); - mCTv = (TextView) findViewById(R.id.contrast); - mCTv.setText(getString(R.string.contrast_str, mCBar.getProgress())); - - mReduceH = (ImageView) findViewById(R.id.reduce_hue); - mReduceH.setOnClickListener(this); - mIncreaseH = (ImageView) findViewById(R.id.increase_hue); - mIncreaseH.setOnClickListener(this); - mReduceS = (ImageView) findViewById(R.id.reduce_saturation); - mReduceS.setOnClickListener(this); - mIncreaseS = (ImageView) findViewById(R.id.increase_saturation); - mIncreaseS.setOnClickListener(this); - mReduceI = (ImageView) findViewById(R.id.reduce_intensity); - mReduceI.setOnClickListener(this); - mIncreaseI = (ImageView) findViewById(R.id.increase_intensity); - mIncreaseI.setOnClickListener(this); - mReduceC = (ImageView) findViewById(R.id.reduce_contrast); - mReduceC.setOnClickListener(this); - mIncreaseC = (ImageView) findViewById(R.id.increase_contrast); - mIncreaseC.setOnClickListener(this); - - mUpdown = (ImageView) findViewById(R.id.up_down); - mUpdown.setOnClickListener(this); - mMore = (ImageView) findViewById(R.id.more); - mMore.setOnClickListener(this); - - mPreviousBtn = (Button) findViewById(R.id.previous_btn); - mPreviousBtn.setOnClickListener(this); - mNewBtn = (Button) findViewById(R.id.new_btn); - mNewBtn.setOnClickListener(this); - mCancelBtn = (Button) findViewById(R.id.cancel); - mCancelBtn.setOnClickListener(this); - mSaveBtn = (Button) findViewById(R.id.save); - mSaveBtn.setOnClickListener(this); - - initBtnsStatus(); - } - - private void initPPService() { - mPPServiceConn = new PPServiceConnection(); - String packetname = "com.qualcomm.display"; - String service = "com.qualcomm.display.PPService"; - Intent i = new Intent(IPPService.class.getName()); - - ComponentName component = new ComponentName(packetname, service); - i.setComponent(component); - - boolean ret = bindService(i, mPPServiceConn, Context.BIND_AUTO_CREATE); - } - - private class PPServiceConnection implements ServiceConnection { - - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - mPPService = IPPService.Stub.asInterface((IBinder) service); - Log.d(TAG, "onServiceConnected, service=" + mPPService); - try { - if (null != mPPService) { - mPPService.startPP(); - restoreSavedHSCI(true); - } - } catch (RemoteException e) { - Log.e(TAG, "startPP exception"); - } - - } - - @Override - public void onServiceDisconnected(ComponentName name) { - if (null != mPPService) { - // end thread - try { - Log.d(TAG, "stopPP"); - mPPService.stopPP(); - } catch (RemoteException e) { - Log.e(TAG, "stopPP exception"); - } - } - mPPService = null; - } - - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode != RESULT_OK) { - Log.i(TAG, "bail due to resultCode=" + resultCode); - return; - } - switch (requestCode) { - case REQUEST_SELECT_FILE: - changePreviewByData(data); - break; - default: - break; - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - menu.add(SELECT_FILE_GROUP1, SELECT_FILE_ITEM, SELECT_FILE_ORDER, - R.string.selectfile_menu); - menu.add(SELECT_FILE_GROUP1, RESET, SELECT_FILE_ORDER, R.string.restore_default_str); - menu.add(SELECT_FILE_GROUP2, RESTORE_DEFAULT_PREVIEW, SELECT_FILE_ORDER, - R.string.restore_preview); - menu.add(SELECT_FILE_GROUP2, SELECT_NEW_FILE_ITEM, SELECT_FILE_ORDER, - R.string.selectnewfile_menu); - menu.add(SELECT_FILE_GROUP2, RESET, SELECT_FILE_ORDER, R.string.restore_default_str); - return true; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - if (canRestorePreview) { - menu.setGroupVisible(SELECT_FILE_GROUP1, false); - menu.setGroupVisible(SELECT_FILE_GROUP2, true); - } else { - menu.setGroupVisible(SELECT_FILE_GROUP1, true); - menu.setGroupVisible(SELECT_FILE_GROUP2, false); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - break; - case SELECT_NEW_FILE_ITEM: - selectPicFromGallery2(); - break; - case SELECT_FILE_ITEM: - selectPicFromGallery2(); - break; - case RESTORE_DEFAULT_PREVIEW: - resotreBackgroundByDefault(); - break; - case RESET: - restoreDefaultHSCI(); - break; - default: - return true; - } - return false; - } - - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - setNewBtnHighlight(); - int id = seekBar.getId(); - switch (id) { - case R.id.hcontrol: - mHueValue = progress; - //The screen hue display value varies from -180 to 180. - mHTv.setText(getString(R.string.hue_str, progress - 180)); - break; - case R.id.scontrol: - mSaturationValue = progress; - //Change the saturation display value varies from (-180, 180) to (-1.0, 1.0). - mSTv.setText(getString(R.string.saturation_str, - ((int) (((progress - 180) * 100) / 180.0)) / 100.0)); - break; - case R.id.ccontrol: - mContrastValue = progress; - //Change the contrast display value varies from (-180, 180) to (-1.0, 1.0). - mCTv.setText(getString(R.string.contrast_str, - ((int) (((progress - 180) * 100) / 180.0)) / 100.0)); - break; - case R.id.icontrol: - mIntensityValue = progress; - //The screen intensity display value varies from -200 to 200. - mITv.setText(getString(R.string.intensity_str, progress - 200)); - break; - default: - break; - - } - Log.i(TAG, "onProgressChanged mHueValue=" + mHueValue + " mSaturationValue=" - + mSaturationValue + " mNewContrastValue=" + mContrastValue + " mIntensityValue=" - + mIntensityValue); - try { - if (null != mPPService && mPPService.getPPStatus()) { - mPPService.updateHSIC(mHueValue, mSaturationValue, mIntensityValue, - mContrastValue); - } - } catch (RemoteException e) { - Log.e(TAG, "updateHSIC exception"); - } - } - - public void onStartTrackingTouch(SeekBar seekBar) { - setActivated(seekBar, true); - } - - public void onStopTrackingTouch(SeekBar seekBar) { - setActivated(seekBar, false); - } - - private void setActivated(SeekBar seekBar, boolean isActivated) { - int id = seekBar.getId(); - switch (id) { - case R.id.hcontrol: - mReduceH.setActivated(isActivated); - mIncreaseH.setActivated(isActivated); - break; - case R.id.scontrol: - mReduceS.setActivated(isActivated); - mIncreaseS.setActivated(isActivated); - break; - case R.id.icontrol: - mReduceI.setActivated(isActivated); - mIncreaseI.setActivated(isActivated); - break; - case R.id.ccontrol: - mReduceC.setActivated(isActivated); - mIncreaseC.setActivated(isActivated); - break; - default: - break; - } - - } - - public void onClick(View v) { - int id = v.getId(); - - switch (id) { - case R.id.cancel: - restoreSavedHSCI(false); - finish(); - break; - case R.id.save: - saveHSCI(); - break; - case R.id.previous_btn: - previousOrNewHSCI(true); - break; - case R.id.new_btn: - previousOrNewHSCI(false); - break; - case R.id.up_down: - upDownHSCISettingLayout(); - break; - case R.id.more: - showMoreMenus(); - break; - case R.id.reduce_hue: - mHBar.setProgress((mHueValue - 1 > mMinHueValue) ? (mHueValue - 1) : mMinHueValue); - break; - case R.id.increase_hue: - mHBar.setProgress((mHueValue + 1 < mMaxHueValue) ? (mHueValue + 1) : mMaxHueValue); - break; - case R.id.reduce_saturation: - mSBar.setProgress((mSaturationValue - 1 > mMinSaturationValue) ? - (mSaturationValue - 1) : mMinSaturationValue); - break; - case R.id.increase_saturation: - mSBar.setProgress((mSaturationValue + 1 < mMaxSaturationValue) ? - (mSaturationValue + 1) : mMaxSaturationValue); - break; - case R.id.reduce_intensity: - mIBar.setProgress((mIntensityValue - 1 > mMinIntensityValue) ? - (mIntensityValue - 1) : mMinIntensityValue); - break; - case R.id.increase_intensity: - mIBar.setProgress((mIntensityValue + 1 < mMaxIntensityValue) ? - (mIntensityValue + 1) : mMaxIntensityValue); - break; - case R.id.reduce_contrast: - mCBar.setProgress((mContrastValue - 1 > mMinContrastValue) ? - (mContrastValue - 1) : mMinContrastValue); - break; - case R.id.increase_contrast: - mCBar.setProgress((mContrastValue + 1 < mMaxContrastValue) ? - (mContrastValue + 1) : mMaxContrastValue); - break; - default: - break; - } - } - - private void selectPicFromGallery2() { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("image/*"); - startActivityForResult(intent, REQUEST_SELECT_FILE); - } - - private void restoreDefaultHSCI() { - mHBar.setProgress(mDefaultHueValue); - mSBar.setProgress(mDefaultSaturationValue); - mIBar.setProgress(mDefaultIntensityValue); - mCBar.setProgress(mDefaultContrastValue); - setNewBtnHighlight(); - } - - private void restoreSavedHSCI(boolean setProgress) { - SharedPreferences share = getSharedPreferences(PREVIEW_STRING_NAME, - Context.MODE_WORLD_WRITEABLE); - int hueValue = share.getInt(COLOR_HUE, mDefaultHueValue); - int saturationValue = share.getInt(COLOR_SATURATION, mDefaultSaturationValue); - int intensityValue = share.getInt(COLOR_INTENSITY, mDefaultIntensityValue); - int contrastValue = share.getInt(COLOR_CONTRAST, mDefaultContrastValue); - if (setProgress) { - mHBar.setProgress(hueValue); - mSBar.setProgress(saturationValue); - mIBar.setProgress(intensityValue); - mCBar.setProgress(contrastValue); - } - Log.i(TAG, "restoreSavedHSCI hueValue=" + hueValue + " saturationValue=" + saturationValue - + " contrastValue=" + contrastValue + " intensityValue=" + intensityValue); - try { - if (null != mPPService && mPPService.getPPStatus()) { - mPPService.updateHSIC(hueValue, saturationValue, intensityValue, contrastValue); - } - } catch (RemoteException e) { - Log.e(TAG, "updateHSIC exception"); - } - } - - private void previewNewHSIC() { - mHBar.setProgress(mHueValue); - mSBar.setProgress(mSaturationValue); - mIBar.setProgress(mIntensityValue); - mCBar.setProgress(mContrastValue); - Log.i(TAG, "previewNewHSIC mHueValue=" + mHueValue + " mSaturationValue=" - + mSaturationValue + " mContrastValue=" + mContrastValue + " mIntensityValue=" - + mIntensityValue); - try { - if (null != mPPService && mPPService.getPPStatus()) { - mPPService.updateHSIC(mHueValue, mSaturationValue, mIntensityValue, - mContrastValue); - } - } catch (RemoteException e) { - Log.e(TAG, "updateHSIC exception"); - } - } - - private void setNewBtnHighlight() { - mPreviousBtn.setBackgroundResource(R.drawable.ic_previous_default); - mNewBtn.setBackgroundResource(R.drawable.ic_new_glow); - mPreviousBtn.setEnabled(true); - mNewBtn.setEnabled(true); - mSaveBtn.setEnabled(true); - - } - - private void initBtnsStatus() { - mPreviousBtn.setBackgroundResource(R.drawable.ic_previous_dis); - mNewBtn.setBackgroundResource(R.drawable.ic_new_dis); - mPreviousBtn.setEnabled(false); - mNewBtn.setEnabled(false); - mSaveBtn.setEnabled(false); - } - - private void previousOrNewHSCI(boolean isPrevious) { - if (View.GONE != mScreenColorLayout.getVisibility()) { - mScreenColorLayout.setVisibility(View.GONE); - mUpdown.setBackgroundResource(R.drawable.up_button); - } - if (isPrevious) { - mPreviousBtn.setBackgroundResource(R.drawable.ic_previous_glow); - mNewBtn.setBackgroundResource(R.drawable.ic_new_default); - mUpdown.setVisibility(View.GONE); - mMore.setVisibility(View.GONE); - restoreSavedHSCI(false); - } else { - mPreviousBtn.setBackgroundResource(R.drawable.ic_previous_default); - mNewBtn.setBackgroundResource(R.drawable.ic_new_glow); - mUpdown.setVisibility(View.VISIBLE); - mMore.setVisibility(View.VISIBLE); - previewNewHSIC(); - } - } - - private void saveHSCI() { - // TODO save HSCI values. - saveHSICPreference(mHueValue, mSaturationValue, mIntensityValue, mContrastValue); - finish(); - } - - private void changePreviewByData(Intent data) { - if (data != null) { - Uri uri = data.getData(); - setBackgroundByUri(uri); - savePreviewKey(uri.toString()); - } - } - - private void setBackgroundByUri(Uri uri) { - InputStream is = null; - try { - is = getContentResolver().openInputStream(uri); - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inJustDecodeBounds = true; - BitmapFactory.decodeStream(is, null, opts); - is.close(); - is = getContentResolver().openInputStream(uri); - opts.inJustDecodeBounds = false; - opts.inSampleSize = calculateInSampleSize(opts, - mRLayout.getWidth(), mRLayout.getHeight()); - Bitmap bm = BitmapFactory.decodeStream(is, null, opts); - BitmapDrawable bd = new BitmapDrawable(bm); - mRLayout.setBackgroundDrawable(bd); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - canRestorePreview = true; - } - - public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { - // Raw height and width of image - final int height = options.outHeight; - final int width = options.outWidth; - int inSampleSize = 1; - - if (height > reqHeight || width > reqWidth) { - - final int halfHeight = height / 2; - final int halfWidth = width / 2; - - // Calculate the largest inSampleSize value that is a power of 2 and keeps both - // height and width larger than the requested height and width. - while ((halfHeight / inSampleSize) > reqHeight - && (halfWidth / inSampleSize) > reqWidth) { - inSampleSize *= 2; - } - } - - return inSampleSize; - } - - private void resotreBackgroundByDefault() { - mRLayout.setBackgroundResource(R.drawable.default_screencolor_setting); - savePreviewKey(""); - canRestorePreview = false; - } - - // use sharepreference to save preview image. - private void savePreviewKey(String value) { - SharedPreferences share = getSharedPreferences(PREVIEW_STRING_NAME, Context.MODE_PRIVATE); - Editor editor = share.edit(); - editor.putString(PREVIEW_STRING_KEY, value); - editor.commit(); - } - - private void saveHSICPreference(int h, int s, int i, int c) { - SharedPreferences share = getSharedPreferences(PREVIEW_STRING_NAME, Context.MODE_PRIVATE); - Editor editor = share.edit(); - editor.putInt(COLOR_HUE, h); - editor.putInt(COLOR_SATURATION, s); - editor.putInt(COLOR_INTENSITY, i); - editor.putInt(COLOR_CONTRAST, c); - editor.commit(); - } - - private String getScreenColorPreviewKey() { - SharedPreferences share = getSharedPreferences(PREVIEW_STRING_NAME, - Context.MODE_WORLD_WRITEABLE | Context.MODE_WORLD_READABLE); - return share.getString(PREVIEW_STRING_KEY, ""); - } - - private void upDownHSCISettingLayout() { - if (View.GONE != mScreenColorLayout.getVisibility()) { - mScreenColorLayout.setVisibility(View.GONE); - mUpdown.setBackgroundResource(R.drawable.up_button); - } else { - mScreenColorLayout.setVisibility(View.VISIBLE); - mUpdown.setBackgroundResource(R.drawable.down_button); - } - } - - private void showMoreMenus() { - PopupMenu popup = new PopupMenu(CustomScreenColor.this, mMore); - Menu menu = popup.getMenu(); - popup.getMenuInflater().inflate(R.menu.screencolor_more, menu); - - if (canRestorePreview) { - menu.removeItem(R.id.selectfile_menu); - } else { - menu.removeItem(R.id.restore_preview); - menu.removeItem(R.id.selectnewfile_menu); - } - - popup.setOnMenuItemClickListener(new MyMenuItemclick()); - popup.show(); - } - - private class MyMenuItemclick implements OnMenuItemClickListener { - @Override - public boolean onMenuItemClick(MenuItem item) { - switch (item.getItemId()) { - case R.id.restore_preview: - resotreBackgroundByDefault(); - return true; - case R.id.selectnewfile_menu: - selectPicFromGallery2(); - return true; - case R.id.selectfile_menu: - selectPicFromGallery2(); - return true; - case R.id.restore_default_str: - restoreDefaultHSCI(); - return true; - } - return true; - } - } -} diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java index 63120e3..8bfff58 100644 --- a/src/com/android/settings/DataUsageSummary.java +++ b/src/com/android/settings/DataUsageSummary.java @@ -25,6 +25,8 @@ import static android.net.NetworkPolicy.WARNING_DISABLED; import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_WLAN_BACKGROUND; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_DATA; import static android.net.NetworkPolicyManager.computeLastCycleBoundary; import static android.net.NetworkPolicyManager.computeNextCycleBoundary; import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER; @@ -127,6 +129,7 @@ import android.widget.Toast; import com.android.internal.logging.MetricsLogger; import com.android.internal.telephony.PhoneConstants; +import com.android.settings.DataUsageUtils; import com.android.settings.drawable.InsetBoundsDrawable; import com.android.settings.net.DataUsageMeteredSettings; import com.android.settings.search.BaseSearchIndexProvider; @@ -176,6 +179,8 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable private static final String TAB_ETHERNET = "ethernet"; private static final String TAG_CONFIRM_DATA_DISABLE = "confirmDataDisable"; + private static final String TAG_CONFIRM_DATA_RESET = "confirmDataReset"; + private static final String TAG_CONFIRM_APP_RESTRICT_CELLULAR = "confirmAppRestrictCellular"; private static final String TAG_CONFIRM_LIMIT = "confirmLimit"; private static final String TAG_CYCLE_EDITOR = "cycleEditor"; private static final String TAG_WARNING_EDITOR = "warningEditor"; @@ -194,6 +199,9 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable private static final int LOADER_CHART_DATA = 2; private static final int LOADER_SUMMARY = 3; + private static final int DATA_USAGE_BACKGROUND_FULL_ACCESS = 0; + private static final int DATA_USAGE_BACKGROUND_WLAN_ACCESS = 1; + private static final int DATA_USAGE_BACKGROUND_NO_ACCESS = 2; private INetworkManagementService mNetworkService; private INetworkStatsService mStatsService; @@ -206,6 +214,7 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable private static final String PREF_FILE = "data_usage"; private static final String PREF_SHOW_WIFI = "show_wifi"; private static final String PREF_SHOW_ETHERNET = "show_ethernet"; + private static final String PREF_ENABLE_DATA_USAGE_NOTIFY = "enable_data_usage_notify"; private SharedPreferences mPrefs; @@ -250,11 +259,17 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable private Button mAppSettings; private LinearLayout mAppSwitches; - private Switch mAppRestrict; + private Switch mAppDataAlert; + private Switch mAppCellularAccess; private View mAppRestrictView; + private View mAppDataAlertView; + private View mAppCellularAccessView; + private Spinner mRestrictSpinner; private boolean mShowWifi = false; private boolean mShowEthernet = false; + private boolean mShowAlerts = false; + private boolean mDataAlertsSupported = false; private NetworkTemplate mTemplate; private ChartData mChartData; @@ -273,6 +288,8 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable private MenuItem mMenuShowEthernet; private MenuItem mMenuSimCards; private MenuItem mMenuCellularNetworks; + private MenuItem mMenuDataAlerts; + private MenuItem mMenuResetStats; private List<SubscriptionInfo> mSubInfoList; private Map<Integer,String> mMobileTagMap; @@ -334,6 +351,7 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable mShowWifi = mPrefs.getBoolean(PREF_SHOW_WIFI, true); mShowEthernet = mPrefs.getBoolean(PREF_SHOW_ETHERNET, false); + mShowAlerts = mPrefs.getBoolean(PREF_ENABLE_DATA_USAGE_NOTIFY, false); // override preferences when no mobile radio if (!hasReadyMobileRadio(context)) { @@ -444,14 +462,51 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable mAppSettings = (Button) mAppDetail.findViewById(R.id.app_settings); - mAppRestrict = new Switch(inflater.getContext()); - mAppRestrict.setClickable(false); - mAppRestrict.setFocusable(false); - mAppRestrictView = inflatePreference(inflater, mAppSwitches, mAppRestrict); + ArrayAdapter<String> restrictAdapter = new ArrayAdapter<String>( + inflater.getContext(), android.R.layout.simple_spinner_dropdown_item, + getResources().getStringArray(R.array.background_data_access_choices)); + + mRestrictSpinner = new Spinner(inflater.getContext()); + mRestrictSpinner.setAdapter(restrictAdapter); + mRestrictSpinner.setOnItemSelectedListener(mAppRestrictListener); + + mAppRestrictView = inflatePreferenceWithInvisibleWidget(inflater, + mAppSwitches, mRestrictSpinner); mAppRestrictView.setClickable(true); mAppRestrictView.setFocusable(true); - mAppRestrictView.setOnClickListener(mAppRestrictListener); + mAppRestrictView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mRestrictSpinner.performClick(); + } + }); mAppSwitches.addView(mAppRestrictView); + + //switch for per app data alert enable/disable + mAppDataAlert = new Switch(inflater.getContext()); + mAppDataAlert.setClickable(false); + mAppDataAlert.setFocusable(false); + mAppDataAlertView = inflatePreference(inflater, mAppSwitches, mAppDataAlert); + mAppDataAlertView.setClickable(true); + mAppDataAlertView.setFocusable(true); + mAppDataAlertView.setOnClickListener(mAppDataAlertListner); + mAppSwitches.addView(mAppDataAlertView); + + // check if content provider is installed. If not, hide data alert switch + mDataAlertsSupported = DataUsageUtils.isDbEnabled(context); + if (!mDataAlertsSupported) { + mAppDataAlertView.setVisibility(View.GONE); + } + + // switch for per app cellular access enabled/disable + mAppCellularAccess = new Switch(inflater.getContext()); + mAppCellularAccess.setClickable(false); + mAppCellularAccess.setFocusable(false); + mAppCellularAccessView = inflatePreference(inflater, mAppSwitches, mAppCellularAccess); + mAppCellularAccessView.setClickable(true); + mAppCellularAccessView.setFocusable(true); + mAppCellularAccessView.setOnClickListener(mAppRestrictCellularListener); + mAppSwitches.addView(mAppCellularAccessView); } mDisclaimer = mHeader.findViewById(R.id.disclaimer); @@ -591,6 +646,17 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable help.setVisible(false); } + mMenuDataAlerts = menu.findItem(R.id.data_usage_menu_data_alerts); + + if (mDataAlertsSupported) { + mMenuDataAlerts.setVisible(!appDetailMode); + } else { + mMenuDataAlerts.setVisible(false); + } + + mMenuResetStats = menu.findItem(R.id.data_usage_menu_reset_stats); + mMenuResetStats.setVisible(!appDetailMode); + updateMenuTitles(); } @@ -612,6 +678,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable } else { mMenuShowEthernet.setTitle(R.string.data_usage_menu_show_ethernet); } + if (mShowAlerts) { + mMenuDataAlerts.setTitle(R.string.data_usage_menu_disable_data_alerts); + } else { + mMenuDataAlerts.setTitle(R.string.data_usage_menu_enable_data_alerts); + } } @Override @@ -658,6 +729,14 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable R.string.data_usage_metered_title, null, this, 0); return true; } + case R.id.data_usage_menu_reset_stats: { + ConfirmDataResetFragment.show(DataUsageSummary.this, mTemplate); + return true; + } + case R.id.data_usage_menu_data_alerts: { + updateShowAlertsState(!mShowAlerts); + return true; + } } return false; } @@ -675,6 +754,13 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable super.onDestroy(); } + private void updateShowAlertsState(boolean showAlert) { + mShowAlerts = showAlert; + mPrefs.edit().putBoolean(PREF_ENABLE_DATA_USAGE_NOTIFY, mShowAlerts).apply(); + updateMenuTitles(); + DataUsageUtils.enableDataUsageService(getContext(), mShowAlerts); + } + /** * Build and assign {@link LayoutTransition} to various containers. Should * only be assigned after initial layout is complete. @@ -1026,17 +1112,52 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable updateDetailData(); - if (UserHandle.isApp(uid) && !mPolicyManager.getRestrictBackground() - && isBandwidthControlEnabled() && hasReadyMobileRadio(context)) { - setPreferenceTitle(mAppRestrictView, R.string.data_usage_app_restrict_background); - setPreferenceSummary(mAppRestrictView, - getString(R.string.data_usage_app_restrict_background_summary)); + if (UserHandle.isApp(uid) && isBandwidthControlEnabled()) { + setPreferenceTitle(mAppRestrictView, R.string.background_data_access); + int backgroundPolicy = getAppRestrictBackground(); + final int summaryResId, position; + if ((backgroundPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { + if ((backgroundPolicy & POLICY_REJECT_ON_WLAN_BACKGROUND) != 0) { + summaryResId = R.string.allow_background_none; + position = DATA_USAGE_BACKGROUND_NO_ACCESS; + } else { + summaryResId = R.string.allow_background_wlan; + position = DATA_USAGE_BACKGROUND_WLAN_ACCESS; + } + } else { + summaryResId = R.string.allow_background_both; + position = DATA_USAGE_BACKGROUND_FULL_ACCESS; + } + setPreferenceSummary(mAppRestrictView, getString(summaryResId)); + mRestrictSpinner.setSelection(position); mAppRestrictView.setVisibility(View.VISIBLE); - mAppRestrict.setChecked(getAppRestrictBackground()); + if (isMobileTab(mCurrentTab) || TAB_3G.equals(mCurrentTab) + || TAB_4G.equals(mCurrentTab)) { + setPreferenceTitle(mAppCellularAccessView, R.string.restrict_cellular_access_title); + setPreferenceSummary(mAppCellularAccessView, + getString(R.string.restrict_cellular_access_summary)); + mAppCellularAccessView.setVisibility(View.VISIBLE); + mAppCellularAccess.setChecked(getAppRestrictCellular()); + } else { + mAppCellularAccessView.setVisibility(View.GONE); + } + + if (mDataAlertsSupported) { + setPreferenceTitle(mAppDataAlertView, R.string.mobile_data_alert); + setPreferenceSummary(mAppDataAlertView, + getString(R.string.mobile_data_alert_summary)); + + mAppDataAlertView.setVisibility(View.VISIBLE); + mAppDataAlert.setChecked(getAppDataAlert()); + } else { + mAppDataAlertView.setVisibility(View.GONE); + } } else { mAppRestrictView.setVisibility(View.GONE); + mAppDataAlertView.setVisibility(View.GONE); + mAppCellularAccessView.setVisibility(View.GONE); } } @@ -1078,18 +1199,34 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable private void setMobileDataEnabled(int subId, boolean enabled) { if (LOGD) Log.d(TAG, "setMobileDataEnabled: subId = " + subId + " enabled = " + enabled); int dataSubId = mSubscriptionManager.getDefaultDataSubId(); - if (subId == dataSubId || TelephonyManager.getDefault().getSimCount() == 1) { - mTelephonyManager.setDataEnabled(subId, enabled); - } else { - // Update mobile data status of a non DDS sub in provider - final Context context = getActivity(); - android.provider.Settings.Global.putInt(context.getContentResolver(), - android.provider.Settings.Global.MOBILE_DATA + subId, enabled ? 1 : 0); - } + mTelephonyManager.setDataEnabled(subId, enabled); mMobileDataEnabled.put(String.valueOf(subId), enabled); updatePolicy(false); } + private void resetDataStats(NetworkTemplate template) { + // kick off background task to reset stats + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + try { + mStatsService.resetDataUsageHistoryForAllUid(mTemplate); + mPolicyEditor.setPolicyLimitBytes(mTemplate, + mPolicyEditor.getPolicyLimitBytes(mTemplate)); + mStatsService.forceUpdate(); + } catch (RemoteException e) { + + } + return null; + } + @Override + protected void onPostExecute (Void result) { + updateBody(); + } + + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + private boolean isNetworkPolicyModifiable(NetworkPolicy policy) { return policy != null && isBandwidthControlEnabled() && mDataEnabled.isChecked() && ActivityManager.getCurrentUser() == UserHandle.USER_OWNER; @@ -1109,18 +1246,106 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable updateMenuTitles(); } - private boolean getAppRestrictBackground() { + private int getAppRestrictBackground() { final int uid = mCurrentApp.key; final int uidPolicy = mPolicyManager.getUidPolicy(uid); - return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0; + + return ((uidPolicy & POLICY_REJECT_METERED_BACKGROUND) | (uidPolicy & + POLICY_REJECT_ON_WLAN_BACKGROUND)); } - private void setAppRestrictBackground(boolean restrictBackground) { + private void setAppRestrictBackground(int newPolicy) { if (LOGD) Log.d(TAG, "setAppRestrictBackground()"); final int uid = mCurrentApp.key; - mPolicyManager.setUidPolicy( - uid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE); - mAppRestrict.setChecked(restrictBackground); + final int currentPolicy = mPolicyManager.getUidPolicy(uid); + + if (newPolicy == currentPolicy) { + return; + } + + if (((newPolicy & POLICY_REJECT_METERED_BACKGROUND) ^ (currentPolicy & + POLICY_REJECT_METERED_BACKGROUND)) != 0 ) { + if ((newPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { + mPolicyManager.addUidPolicy(uid, POLICY_REJECT_METERED_BACKGROUND); + } else { + mPolicyManager.removeUidPolicy(uid, POLICY_REJECT_METERED_BACKGROUND); + } + } + + if (((newPolicy & POLICY_REJECT_ON_WLAN_BACKGROUND) ^ (currentPolicy & + POLICY_REJECT_ON_WLAN_BACKGROUND)) != 0 ) { + if ((newPolicy & POLICY_REJECT_ON_WLAN_BACKGROUND) != 0) { + mPolicyManager.addUidPolicy(uid, POLICY_REJECT_ON_WLAN_BACKGROUND); + } else { + mPolicyManager.removeUidPolicy(uid, POLICY_REJECT_ON_WLAN_BACKGROUND); + } + } + + final int summaryResId; + if ((newPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { + if ((newPolicy & POLICY_REJECT_ON_WLAN_BACKGROUND) != 0) { + summaryResId = R.string.allow_background_none; + } else { + summaryResId = R.string.allow_background_wlan; + } + } else { + summaryResId = R.string.allow_background_both; + } + setPreferenceSummary(mAppRestrictView, getString(summaryResId)); + } + + private boolean getAppRestrictCellular() { + final int uid = mCurrentApp.key; + final int uidPolicy = mPolicyManager.getUidPolicy(uid); + return (uidPolicy & POLICY_REJECT_ON_DATA) != 0; + } + + private void setAppRestrictCellular(boolean restrictCellular) { + if (LOGD) Log.d(TAG, "setAppRestrictCellular()"); + final int uid = mCurrentApp.key; + if (restrictCellular) { + mPolicyManager.addUidPolicy(uid, POLICY_REJECT_ON_DATA); + } else { + mPolicyManager.removeUidPolicy(uid, POLICY_REJECT_ON_DATA); + } + mAppCellularAccess.setChecked(restrictCellular); + } + + + private void setAppDataAlert(boolean enableDataAlert) { + final int uid = mCurrentApp.key; + + // Get app's details to send to the DataUsage Provider. Don't block if not in the + // DetailProvider cache. (should be in the cache, as the app's label had already + // been displayed in the list of apps) + UidDetail detail = mUidDetailProvider.getUidDetail(uid, false); + String label = detail != null ? detail.label.toString() : ""; + + try { + DataUsageUtils.enableApp(getContext(), uid, enableDataAlert, label); + } catch (Exception e) { + //content provider may not be installed. + Log.d(TAG, "Unable to set data alert state"); + return; + } + mAppDataAlert.setChecked(enableDataAlert); + + // automatically enable global alert for notifications when enabling first per app alert + if (enableDataAlert && !mShowAlerts) { + updateShowAlertsState(true); + } + } + + private boolean getAppDataAlert() { + final int uid = mCurrentApp.key; + + try { + return DataUsageUtils.isAppEnabled(getContext(), uid); + } catch (Exception e) { + //content provider may not be installed. + Log.d(TAG, "Unable to get data alert state"); + return false; + } } /** @@ -1298,22 +1523,53 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable } }; - private View.OnClickListener mAppRestrictListener = new View.OnClickListener() { + private AdapterView.OnItemSelectedListener mAppRestrictListener = + new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View v, int position, long id) { + final int backgroundPolicy; + + if (position == DATA_USAGE_BACKGROUND_WLAN_ACCESS) { + backgroundPolicy = POLICY_REJECT_METERED_BACKGROUND; + } else if (position == DATA_USAGE_BACKGROUND_NO_ACCESS) { + backgroundPolicy = POLICY_REJECT_METERED_BACKGROUND | + POLICY_REJECT_ON_WLAN_BACKGROUND; + } else { + backgroundPolicy = DATA_USAGE_BACKGROUND_FULL_ACCESS; + } + setAppRestrictBackground(backgroundPolicy); + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + // noop + } + }; + + private View.OnClickListener mAppRestrictCellularListener = new View.OnClickListener() { @Override public void onClick(View v) { - final boolean restrictBackground = !mAppRestrict.isChecked(); + final boolean restrictCellular = !mAppCellularAccess.isChecked(); - if (restrictBackground) { + if (restrictCellular) { // enabling restriction; show confirmation dialog which - // eventually calls setRestrictBackground() once user + // eventually calls setRestrictCellular() once user // confirms. - ConfirmAppRestrictFragment.show(DataUsageSummary.this); + ConfirmAppRestrictCellularFragment.show(DataUsageSummary.this); } else { - setAppRestrictBackground(false); + setAppRestrictCellular(false); } } }; + private View.OnClickListener mAppDataAlertListner = new View.OnClickListener() { + @Override + public void onClick(View v) { + final boolean enableDataAlert = !mAppDataAlert.isChecked(); + setAppDataAlert(enableDataAlert); + } + }; + private OnItemClickListener mListListener = new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { @@ -2199,6 +2455,45 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable } /** + * Dialog to request user confirmation before resetting data. + */ + public static class ConfirmDataResetFragment extends DialogFragment { + static NetworkTemplate mTemplate; + public static void show(DataUsageSummary parent, NetworkTemplate template) { + mTemplate = template; + if (!parent.isAdded()) return; + + final ConfirmDataResetFragment dialog = new ConfirmDataResetFragment(); + dialog.setTargetFragment(parent, 0); + dialog.show(parent.getFragmentManager(), TAG_CONFIRM_DATA_RESET); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Context context = getActivity(); + + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.data_usage_menu_reset_stats); + builder.setMessage(R.string.reset_data_stats_msg); + + builder.setPositiveButton(R.string.reset_stats_confirm, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + final DataUsageSummary target = (DataUsageSummary) getTargetFragment(); + if (target != null) { + // TODO: extend to modify policy enabled flag. + target.resetDataStats(mTemplate); + } + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + + return builder.create(); + } + } + + /** * Dialog to request user confirmation before setting * {@link INetworkPolicyManager#setRestrictBackground(boolean)}. */ @@ -2267,15 +2562,16 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable /** * Dialog to request user confirmation before setting - * {@link #POLICY_REJECT_METERED_BACKGROUND}. + * {@link #POLICY_REJECT_ON_DATA}. */ - public static class ConfirmAppRestrictFragment extends DialogFragment { + public static class ConfirmAppRestrictCellularFragment extends DialogFragment { public static void show(DataUsageSummary parent) { if (!parent.isAdded()) return; - final ConfirmAppRestrictFragment dialog = new ConfirmAppRestrictFragment(); + final ConfirmAppRestrictCellularFragment dialog = new + ConfirmAppRestrictCellularFragment(); dialog.setTargetFragment(parent, 0); - dialog.show(parent.getFragmentManager(), TAG_CONFIRM_APP_RESTRICT); + dialog.show(parent.getFragmentManager(), TAG_CONFIRM_APP_RESTRICT_CELLULAR); } @Override @@ -2283,15 +2579,15 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable final Context context = getActivity(); final AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.data_usage_app_restrict_dialog_title); - builder.setMessage(R.string.data_usage_app_restrict_dialog); + builder.setTitle(R.string.restrict_cellular_access_dialog_title); + builder.setMessage(R.string.restrict_cellular_access_dialog_summary); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { final DataUsageSummary target = (DataUsageSummary) getTargetFragment(); if (target != null) { - target.setAppRestrictBackground(true); + target.setAppRestrictCellular(true); } } }); @@ -2517,6 +2813,16 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable return view; } + private static View inflatePreferenceWithInvisibleWidget(LayoutInflater inflater, + ViewGroup root, View widget) { + final ViewGroup view = (ViewGroup) inflater.inflate(R.layout.preference, root, false); + view.addView(widget, 0); + final ViewGroup.LayoutParams lp = widget.getLayoutParams(); + lp.width = 0; + widget.setLayoutParams(lp); + return view; + } + /** * Test if any networks are currently limited. */ diff --git a/src/com/android/settings/DataUsageUtils.java b/src/com/android/settings/DataUsageUtils.java new file mode 100644 index 0000000..09b6b10 --- /dev/null +++ b/src/com/android/settings/DataUsageUtils.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2016 The CyanogenMod project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.util.Log; + +import cyanogenmod.providers.DataUsageContract; + +/** + * This class contains utility helper functions for accessing DataUsageProvider + */ +public class DataUsageUtils { + private static final String TAG = DataUsageUtils.class.getSimpleName(); + private static final String WHERE_CLAUSE = DataUsageContract.UID + " = ? "; + private static final int DATAUSAGE_SERVICE_ALARM_ID = 0x102030; + private static boolean DEBUG = true; + + public static void addApp(Context context, int uid, String label) { + if (DEBUG) { + Log.v(TAG, "addApp: uid:" + uid + " label:" + label); + } + + ContentValues values = new ContentValues(); + + values.put(DataUsageContract.UID, uid); + values.put(DataUsageContract.LABEL, label); + + context.getContentResolver().insert( + DataUsageContract.CONTENT_URI, + values + ); + } + + public static void removeApp(Context context, int uid) { + if (DEBUG) { + Log.v(TAG, "removeApp: uid:" + uid); + } + context.getContentResolver().delete( + DataUsageContract.CONTENT_URI, + WHERE_CLAUSE, + new String [] { String.valueOf(uid) } + ); + } + + public static void enableApp(Context context, int uid, boolean enable) { + enableApp(context, uid, enable, null); + } + + public static void enableApp(Context context, int uid, boolean enable, String label) { + if (DEBUG) { + Log.v(TAG, "enableApp: uid:" + uid + " enable:" + enable + + (label == null ? "" : " label:" + label)); + } + ContentValues values = new ContentValues(); + + values.put(DataUsageContract.ENABLE, enable); + values.put(DataUsageContract.ACTIVE, 0); + if (label != null) { + values.put(DataUsageContract.LABEL, label); + } + context.getContentResolver().update( + DataUsageContract.CONTENT_URI, + values, + WHERE_CLAUSE, + new String [] { String.valueOf(uid) } + ); + } + + public static boolean isDbEnabled(Context context) { + boolean dbEnabled = false; + try (Cursor cursor = context.getContentResolver().query( + DataUsageContract.CONTENT_URI, + null, + WHERE_CLAUSE, + new String [] { "0" }, + null)) { + dbEnabled = true; + } + return dbEnabled; + } + + public static boolean isAppEnabled(Context context, int uid) { + boolean appEnabled = false; + + try (Cursor cursor = context.getContentResolver().query( + DataUsageContract.CONTENT_URI, + null, + WHERE_CLAUSE, + new String [] { String.valueOf(uid) }, + null)) { + if (cursor.moveToFirst()) { + appEnabled = cursor.getInt(DataUsageContract.COLUMN_OF_ENABLE) == 1; + } + } + + if (DEBUG) { + Log.v(TAG, "isAppEnabled: uid:" + uid + " enabled:" + appEnabled); + } + + return appEnabled; + } + + public static void enableDataUsageService(Context context, boolean enable) { + Intent intent = new Intent(); + intent.setAction("org.cyanogenmod.providers.datausage.enable"); + intent.putExtra("enable", enable); + context.sendBroadcast(intent); + } +} diff --git a/src/com/android/settings/DateChangeReceiver.java b/src/com/android/settings/DateChangeReceiver.java new file mode 100644 index 0000000..6a3ec88 --- /dev/null +++ b/src/com/android/settings/DateChangeReceiver.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class DateChangeReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + DateTimeSettings.updateLocaleStrings(); + } +} diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java index 8a9e2ad..34753ef 100644 --- a/src/com/android/settings/DateTimeSettings.java +++ b/src/com/android/settings/DateTimeSettings.java @@ -40,9 +40,12 @@ import android.widget.TimePicker; import com.android.internal.logging.MetricsLogger; import com.android.settingslib.datetime.ZoneGetter; +import libcore.icu.TimeZoneNames; +import java.text.DateFormatSymbols; import java.util.Calendar; import java.util.Date; +import java.util.Locale; public class DateTimeSettings extends SettingsPreferenceFragment implements OnSharedPreferenceChangeListener, @@ -329,6 +332,16 @@ public class DateTimeSettings extends SettingsPreferenceFragment if (when / 1000 < Integer.MAX_VALUE) { ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when); } + updateLocaleStrings(); + } + + static void updateLocaleStrings() { + // If a device was boot up with date 1970 and then date changes to some later time, + // the wrong string might be cached if the country's zones have changed. + // See external/icu/icu4c/source/data/misc/metaZones.txt for complete mapping + TimeZoneNames.clearLocaleCache(); + Locale locale = Locale.getDefault(); + DateFormatSymbols.getInstance(locale).setZoneStrings(TimeZoneNames.getZoneStrings(locale)); } /* package */ static void setTime(Context context, int hourOfDay, int minute) { diff --git a/src/com/android/settings/DefaultRingtonePreference.java b/src/com/android/settings/DefaultRingtonePreference.java index d3cbe5a..4bf2cfa 100644 --- a/src/com/android/settings/DefaultRingtonePreference.java +++ b/src/com/android/settings/DefaultRingtonePreference.java @@ -55,7 +55,11 @@ public class DefaultRingtonePreference extends RingtonePreference { @Override protected Uri onRestoreRingtone() { - return RingtoneManager.getActualDefaultRingtoneUri(getContext(), getRingtoneType()); + if (getRingtoneType() == RingtoneManager.TYPE_RINGTONE) { + return RingtoneManager.getActualRingtoneUriBySubId(getContext(), getSubId()); + } else { + return RingtoneManager.getActualDefaultRingtoneUri(getContext(), getRingtoneType()); + } } - + } diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java index d7a4145..b5b89cb 100644 --- a/src/com/android/settings/DevelopmentSettings.java +++ b/src/com/android/settings/DevelopmentSettings.java @@ -79,12 +79,14 @@ import android.widget.TextView; import android.widget.Toast; import com.android.internal.logging.MetricsLogger; +import com.android.settings.Settings.AppOpsSummaryActivity; import com.android.settings.fuelgauge.InactiveApps; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settings.widget.SwitchBar; import cyanogenmod.providers.CMSettings; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -177,6 +179,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment private static final String ROOT_ACCESS_KEY = "root_access"; private static final String ROOT_ACCESS_PROPERTY = "persist.sys.root_access"; + private static final String ROOT_APPOPS_KEY = "root_appops"; + private static final String UPDATE_RECOVERY_KEY = "update_recovery"; private static final String UPDATE_RECOVERY_PROPERTY = "persist.sys.recovery_update"; @@ -210,6 +214,9 @@ public class DevelopmentSettings extends SettingsPreferenceFragment private static final int[] MOCK_LOCATION_APP_OPS = new int[] {AppOpsManager.OP_MOCK_LOCATION}; private static final String MULTI_WINDOW_SYSTEM_PROPERTY = "persist.sys.debug.multi_window"; + + private static final String SUPERUSER_BINARY_PATH = "/system/xbin/su"; + private IWindowManager mWindowManager; private IBackupManager mBackupManager; private DevicePolicyManager mDpm; @@ -288,6 +295,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment private PreferenceScreen mDevelopmentTools; private ColorModePreference mColorModePreference; + private Preference mRootAppops; + private SwitchPreference mAdvancedReboot; private SwitchPreference mUpdateRecovery; @@ -473,8 +482,20 @@ public class DevelopmentSettings extends SettingsPreferenceFragment mRootAccess = (ListPreference) findPreference(ROOT_ACCESS_KEY); mRootAccess.setOnPreferenceChangeListener(this); + + mRootAppops = (Preference) findPreference(ROOT_APPOPS_KEY); + mRootAppops.setOnPreferenceClickListener(this); + if (!removeRootOptionsIfRequired()) { + if (isRootForAppsAvailable()) { + mRootAccess.setEntries(R.array.root_access_entries); + mRootAccess.setEntryValues(R.array.root_access_values); + } else { + mRootAccess.setEntries(R.array.root_access_entries_adb); + mRootAccess.setEntryValues(R.array.root_access_values_adb); + } mAllPrefs.add(mRootAccess); + mAllPrefs.add(mRootAppops); } mDevelopmentTools = (PreferenceScreen) findPreference(DEVELOPMENT_TOOLS); @@ -498,6 +519,15 @@ public class DevelopmentSettings extends SettingsPreferenceFragment removePreference(COLOR_TEMPERATURE_KEY); mColorTemperaturePreference = null; } + + if (!getResources().getBoolean(R.bool.config_enableRecoveryUpdater)) { + removePreference(mUpdateRecovery); + mUpdateRecovery = null; + if (SystemProperties.getBoolean(UPDATE_RECOVERY_PROPERTY, false)) { + SystemProperties.set(UPDATE_RECOVERY_PROPERTY, "false"); + pokeSystemProperties(); + } + } } private ListPreference addListPreference(String prefKey) { @@ -733,7 +763,9 @@ public class DevelopmentSettings extends SettingsPreferenceFragment updateRootAccessOptions(); updateAdvancedRebootOptions(); updateDevelopmentShortcutOptions(); - updateUpdateRecoveryOptions(); + if (mUpdateRecovery != null) { + updateUpdateRecoveryOptions(); + } if (mColorTemperaturePreference != null) { updateColorTemperature(); } @@ -809,7 +841,9 @@ public class DevelopmentSettings extends SettingsPreferenceFragment resetAdbNotifyOptions(); resetVerifyAppsOverUsbOptions(); resetDevelopmentShortcutOptions(); - resetUpdateRecoveryOptions(); + if (mUpdateRecovery != null) { + resetUpdateRecoveryOptions(); + } writeAnimationScaleOption(0, mWindowAnimationScale, null); writeAnimationScaleOption(1, mTransitionAnimationScale, null); writeAnimationScaleOption(2, mAnimatorDurationScale, null); @@ -830,6 +864,21 @@ public class DevelopmentSettings extends SettingsPreferenceFragment mRootAccess.setValue(value); mRootAccess.setSummary(getResources() .getStringArray(R.array.root_access_entries)[Integer.valueOf(value)]); + + if (mRootAppops != null) { + mRootAppops.setEnabled(isRootForAppsEnabled()); + } + } + + private boolean isRootForAppsAvailable() { + boolean exists = false; + try { + File f = new File(SUPERUSER_BINARY_PATH); + exists = f.exists(); + } catch (SecurityException e) { + // Ignore + } + return exists; } public static boolean isRootForAppsEnabled() { @@ -845,10 +894,10 @@ public class DevelopmentSettings extends SettingsPreferenceFragment if (Integer.valueOf(newValue.toString()) < 2 && !oldValue.equals(newValue) && "1".equals(SystemProperties.get("service.adb.root", "0"))) { SystemProperties.set("service.adb.root", "0"); - Settings.Secure.putInt(getActivity().getContentResolver(), - Settings.Secure.ADB_ENABLED, 0); - Settings.Secure.putInt(getActivity().getContentResolver(), - Settings.Secure.ADB_ENABLED, 1); + Settings.Global.putInt(getActivity().getContentResolver(), + Settings.Global.ADB_ENABLED, 0); + Settings.Global.putInt(getActivity().getContentResolver(), + Settings.Global.ADB_ENABLED, 1); } updateRootAccessOptions(); } @@ -858,10 +907,10 @@ public class DevelopmentSettings extends SettingsPreferenceFragment SystemProperties.set(ROOT_ACCESS_PROPERTY, "0"); if (!oldValue.equals("0") && "1".equals(SystemProperties.get("service.adb.root", "0"))) { SystemProperties.set("service.adb.root", "0"); - Settings.Secure.putInt(getActivity().getContentResolver(), - Settings.Secure.ADB_ENABLED, 0); - Settings.Secure.putInt(getActivity().getContentResolver(), - Settings.Secure.ADB_ENABLED, 1); + Settings.Global.putInt(getActivity().getContentResolver(), + Settings.Global.ADB_ENABLED, 0); + Settings.Global.putInt(getActivity().getContentResolver(), + Settings.Global.ADB_ENABLED, 1); } updateRootAccessOptions(); } @@ -920,6 +969,10 @@ public class DevelopmentSettings extends SettingsPreferenceFragment private void updatePasswordSummary() { try { + if (mBackupManager == null) { + Log.e(TAG, "Backup Manager is unavailable!"); + return; + } if (mBackupManager.hasBackupPassword()) { mPassword.setSummary(R.string.local_backup_password_summary_change); } else { @@ -1576,14 +1629,15 @@ public class DevelopmentSettings extends SettingsPreferenceFragment updateLogdSizeValues(); } - private void updateUsbConfigurationValues() { + private void updateUsbConfigurationValues(boolean isUnlocked) { if (mUsbConfiguration != null) { UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); String[] values = getResources().getStringArray(R.array.usb_configuration_values); String[] titles = getResources().getStringArray(R.array.usb_configuration_titles); int index = 0; - for (int i = 0; i < titles.length; i++) { + // Assume if !isUnlocked -> charging, which should be at index 0 + for (int i = 0; i < titles.length && isUnlocked; i++) { if (manager.isFunctionEnabled(values[i])) { index = i; break; @@ -1598,10 +1652,11 @@ public class DevelopmentSettings extends SettingsPreferenceFragment private void writeUsbConfigurationOption(Object newValue) { UsbManager manager = (UsbManager)getActivity().getSystemService(Context.USB_SERVICE); String function = newValue.toString(); - manager.setCurrentFunction(function); if (function.equals("none")) { + manager.setCurrentFunction(null); manager.setUsbDataUnlocked(false); } else { + manager.setCurrentFunction(function); manager.setUsbDataUnlocked(true); } } @@ -1756,10 +1811,12 @@ public class DevelopmentSettings extends SettingsPreferenceFragment } private void confirmEnableOemUnlock() { - DialogInterface.OnClickListener onConfirmListener = new DialogInterface.OnClickListener() { + DialogInterface.OnClickListener onEnableOemListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - Utils.setOemUnlockEnabled(getActivity(), true); + if (which == DialogInterface.BUTTON_POSITIVE) { + Utils.setOemUnlockEnabled(getActivity(), true); + } updateAllOptions(); } }; @@ -1767,8 +1824,9 @@ public class DevelopmentSettings extends SettingsPreferenceFragment new AlertDialog.Builder(getActivity()) .setTitle(R.string.confirm_enable_oem_unlock_title) .setMessage(R.string.confirm_enable_oem_unlock_text) - .setPositiveButton(R.string.enable_text, onConfirmListener) - .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(R.string.enable_text, onEnableOemListener) + .setNegativeButton(android.R.string.cancel, onEnableOemListener) + .setCancelable(false) .create() .show(); } @@ -1787,6 +1845,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment .setMessage(R.string.confirm_enable_multi_window_text) .setPositiveButton(R.string.enable_text, onConfirmListener) .setNegativeButton(android.R.string.cancel, onConfirmListener) + .setCancelable(false) .create() .show(); } @@ -1809,8 +1868,9 @@ public class DevelopmentSettings extends SettingsPreferenceFragment } } - public static void initializeUpdateRecoveryOption() { - if (TextUtils.isEmpty(SystemProperties.get(UPDATE_RECOVERY_PROPERTY))) { + public static void initializeUpdateRecoveryOption(Context context) { + if (TextUtils.isEmpty(SystemProperties.get(UPDATE_RECOVERY_PROPERTY)) && + context.getResources().getBoolean(R.bool.config_enableRecoveryUpdater)) { resetUpdateRecoveryOptions(); } } @@ -1882,6 +1942,13 @@ public class DevelopmentSettings extends SettingsPreferenceFragment preference == mTransitionAnimationScale || preference == mAnimatorDurationScale) { ((AnimationScalePreference) preference).click(); + } else if (preference == mRootAppops) { + Activity mActivity = getActivity(); + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.putExtra("appops_tab", getString(R.string.app_ops_categories_su)); + intent.setClass(mActivity, AppOpsSummaryActivity.class); + mActivity.startActivity(intent); + return true; } return false; } @@ -2263,7 +2330,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment private BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - updateUsbConfigurationValues(); + boolean isUnlocked = intent.getBooleanExtra(UsbManager.USB_DATA_UNLOCKED, false); + updateUsbConfigurationValues(isUnlocked); } }; diff --git a/src/com/android/settings/DeviceAdminSettings.java b/src/com/android/settings/DeviceAdminSettings.java index f0b3070..1f05131 100644 --- a/src/com/android/settings/DeviceAdminSettings.java +++ b/src/com/android/settings/DeviceAdminSettings.java @@ -337,6 +337,7 @@ public class DeviceAdminSettings extends ListFragment { } vh.checkbox.setEnabled(enabled); vh.name.setEnabled(enabled); + vh.name.setSelected(true); vh.description.setEnabled(enabled); vh.icon.setEnabled(enabled); } diff --git a/src/com/android/settings/DeviceInfoSettings.java b/src/com/android/settings/DeviceInfoSettings.java index 949eaab..39eaa5a 100644 --- a/src/com/android/settings/DeviceInfoSettings.java +++ b/src/com/android/settings/DeviceInfoSettings.java @@ -17,6 +17,8 @@ package com.android.settings; import android.app.Activity; +import android.content.ClipData; +import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -43,6 +45,7 @@ import android.text.format.DateFormat; import android.util.Log; import android.widget.Toast; +import cyanogenmod.hardware.CMHardwareManager; import com.android.internal.logging.MetricsLogger; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Index; @@ -91,10 +94,13 @@ public class DeviceInfoSettings extends SettingsPreferenceFragment implements In private static final String KEY_CM_UPDATES = "cm_updates"; static final int TAPS_TO_BE_A_DEVELOPER = 7; + static final int TAPS_TO_SHOW_DEVICEID = 7; long[] mHits = new long[3]; int mDevHitCountdown; + int mDevIdCountdown; Toast mDevHitToast; + Toast mDevIdToast; @Override protected int getMetricsCategory() { @@ -134,8 +140,12 @@ public class DeviceInfoSettings extends SettingsPreferenceFragment implements In setStringSummary(KEY_DEVICE_MODEL, Build.MODEL); setStringSummary(KEY_BUILD_NUMBER, Build.DISPLAY); findPreference(KEY_BUILD_NUMBER).setEnabled(true); - findPreference(KEY_KERNEL_VERSION).setSummary(getFormattedKernelVersion()); - setValueSummary(KEY_MOD_VERSION, cyanogenmod.os.Build.CYANOGENMOD_DISPLAY_VERSION); + + final Preference kernelPref = findPreference(KEY_KERNEL_VERSION); + kernelPref.setEnabled(true); + kernelPref.setSummary(getFormattedKernelVersion()); + findPreference(KEY_MOD_VERSION).setSummary( + cyanogenmod.os.Build.CYANOGENMOD_DISPLAY_VERSION); findPreference(KEY_MOD_VERSION).setEnabled(true); setValueSummary(KEY_MOD_BUILD_DATE, "ro.build.date"); setExplicitValueSummary(KEY_MOD_API_LEVEL, constructApiLevelString()); @@ -226,6 +236,8 @@ public class DeviceInfoSettings extends SettingsPreferenceFragment implements In Context.MODE_PRIVATE).getBoolean(DevelopmentSettings.PREF_SHOW, android.os.Build.TYPE.equals("eng")) ? -1 : TAPS_TO_BE_A_DEVELOPER; mDevHitToast = null; + mDevIdCountdown = TAPS_TO_SHOW_DEVICEID; + mDevIdToast = null; } @Override @@ -262,6 +274,42 @@ public class DeviceInfoSettings extends SettingsPreferenceFragment implements In Log.e(LOG_TAG, "Unable to start activity " + intent.toString()); } } + } else if (preference.getKey().equals(KEY_KERNEL_VERSION)) { + + mDevIdCountdown --; + if (mDevIdCountdown == 0) { + final CMHardwareManager hwMgr = CMHardwareManager.getInstance(getActivity().getApplicationContext()); + final String deviceID = hwMgr.getUniqueDeviceId(); + CharSequence msg; + if (deviceID == null) { + msg = getText(R.string.show_device_id_failed_cm); + } + else { + final ClipboardManager clipboardMgr = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + clipboardMgr.setPrimaryClip(ClipData.newPlainText(getResources(). + getString(R.string.show_device_id_clipboard_label), + deviceID)); + msg = getResources().getString( + R.string.show_device_id_copied_cm, deviceID); + } + + mDevIdToast = Toast.makeText(getActivity(), msg, + Toast.LENGTH_LONG); + mDevIdToast.show(); + mDevIdCountdown = TAPS_TO_SHOW_DEVICEID; + } + else if (mDevIdCountdown > 0 + && mDevIdCountdown < (TAPS_TO_SHOW_DEVICEID-2)) { + + if (mDevIdToast != null) { + mDevIdToast.cancel(); + } + mDevIdToast = Toast.makeText(getActivity(), getResources().getQuantityString( + R.plurals.show_device_id_countdown_cm, mDevIdCountdown, mDevIdCountdown), + Toast.LENGTH_SHORT); + mDevIdToast.show(); + } + } else if (preference.getKey().equals(KEY_BUILD_NUMBER)) { // Don't enable developer options for secondary users. if (UserHandle.myUserId() != UserHandle.USER_OWNER) return true; diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java index 399e1eb..47efd2f 100644 --- a/src/com/android/settings/DisplaySettings.java +++ b/src/com/android/settings/DisplaySettings.java @@ -20,6 +20,7 @@ import com.android.internal.logging.MetricsLogger; import android.app.AlertDialog; import android.content.DialogInterface; +import android.content.SharedPreferences; import android.preference.CheckBoxPreference; import android.os.UserHandle; @@ -52,8 +53,6 @@ import android.app.UiModeManager; import android.app.admin.DevicePolicyManager; import android.content.ContentResolver; import android.content.Context; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.content.res.Resources; import android.hardware.Sensor; @@ -84,6 +83,9 @@ import java.util.ArrayList; import java.util.List; import com.android.settings.Utils; import com.android.settings.cyanogenmod.DisplayRotation; + +import cyanogenmod.hardware.CMHardwareManager; +import cyanogenmod.hardware.LiveDisplayManager; import cyanogenmod.providers.CMSettings; public class DisplaySettings extends SettingsPreferenceFragment implements @@ -112,12 +114,15 @@ public class DisplaySettings extends SettingsPreferenceFragment implements private static final String KEY_WAKE_WHEN_PLUGGED_OR_UNPLUGGED = "wake_when_plugged_or_unplugged"; private static final String KEY_NOTIFICATION_LIGHT = "notification_light"; private static final String KEY_BATTERY_LIGHT = "battery_light"; + private static final String KEY_LIVEDISPLAY = "live_display"; + private static final String KEY_HIGH_TOUCH_SENSITIVITY = "high_touch_sensitivity"; private static final int DLG_GLOBAL_CHANGE_WARNING = 1; private ListPreference mLcdDensityPreference; private FontDialogPreference mFontSizePref; private PreferenceScreen mDisplayRotationPreference; + private PreferenceScreen mLiveDisplayPreference; private final Configuration mCurConfig = new Configuration(); @@ -128,10 +133,13 @@ public class DisplaySettings extends SettingsPreferenceFragment implements private SwitchPreference mLiftToWakePreference; private SwitchPreference mDozePreference; private SwitchPreference mTapToWakePreference; + private SwitchPreference mHighTouchSensitivity; private SwitchPreference mProximityCheckOnWakePreference; private SwitchPreference mAutoBrightnessPreference; private SwitchPreference mWakeWhenPluggedOrUnplugged; + private CMHardwareManager mHardware; + private ContentObserver mAccelerometerRotationObserver = new ContentObserver(new Handler()) { @Override @@ -162,6 +170,8 @@ public class DisplaySettings extends SettingsPreferenceFragment implements final ContentResolver resolver = activity.getContentResolver(); addPreferencesFromResource(R.xml.display); + mHardware = CMHardwareManager.getInstance(activity); + PreferenceCategory displayPrefs = (PreferenceCategory) findPreference(KEY_CATEGORY_DISPLAY); PreferenceCategory interfacePrefs = (PreferenceCategory) @@ -172,6 +182,11 @@ public class DisplaySettings extends SettingsPreferenceFragment implements mAccelerometer.setPersistent(false); } + mLiveDisplayPreference = (PreferenceScreen) findPreference(KEY_LIVEDISPLAY); + if (!LiveDisplayManager.getInstance(getActivity()).getConfig().isAvailable()) { + displayPrefs.removePreference(mLiveDisplayPreference); + } + mScreenSaverPreference = findPreference(KEY_SCREEN_SAVER); if (mScreenSaverPreference != null && getResources().getBoolean( @@ -287,6 +302,16 @@ public class DisplaySettings extends SettingsPreferenceFragment implements } } + mHighTouchSensitivity = (SwitchPreference) findPreference(KEY_HIGH_TOUCH_SENSITIVITY); + if (!mHardware.isSupported( + CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { + displayPrefs.removePreference(mHighTouchSensitivity); + mHighTouchSensitivity = null; + } else { + mHighTouchSensitivity.setChecked( + mHardware.get(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)); + } + mProximityCheckOnWakePreference = (SwitchPreference) findPreference(KEY_PROXIMITY_WAKE); boolean proximityCheckOnWake = getResources().getBoolean( org.cyanogenmod.platform.internal.R.bool.config_proximityCheckOnWake); @@ -294,7 +319,13 @@ public class DisplaySettings extends SettingsPreferenceFragment implements if (displayPrefs != null && mProximityCheckOnWakePreference != null) { displayPrefs.removePreference(mProximityCheckOnWakePreference); } - CMSettings.System.putInt(getContentResolver(), CMSettings.System.PROXIMITY_ON_WAKE, 1); + CMSettings.System.putInt(getContentResolver(), CMSettings.System.PROXIMITY_ON_WAKE, 0); + } else { + boolean proximityCheckOnWakeDefault = getResources().getBoolean( + org.cyanogenmod.platform.internal.R.bool.config_proximityCheckOnWakeEnabledByDefault); + mProximityCheckOnWakePreference.setChecked(CMSettings.System.getInt(getContentResolver(), + CMSettings.System.PROXIMITY_ON_WAKE, + (proximityCheckOnWakeDefault ? 1 : 0)) == 1); } mWakeWhenPluggedOrUnplugged = @@ -664,6 +695,12 @@ public class DisplaySettings extends SettingsPreferenceFragment implements } else if (preference == mAccelerometer) { RotationPolicy.setRotationLockForAccessibility(getActivity(), !mAccelerometer.isChecked()); + } else if (preference == mHighTouchSensitivity) { + boolean mHighTouchSensitivityEnable = mHighTouchSensitivity.isChecked(); + CMSettings.System.putInt(getActivity().getContentResolver(), + CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE, + mHighTouchSensitivityEnable ? 1 : 0); + return true; } return super.onPreferenceTreeClick(preferenceScreen, preference); @@ -783,6 +820,8 @@ public class DisplaySettings extends SettingsPreferenceFragment implements @Override public List<String> getNonIndexableKeys(Context context) { + final CMHardwareManager hardware = CMHardwareManager.getInstance(context); + ArrayList<String> result = new ArrayList<String>(); if (!context.getResources().getBoolean( com.android.internal.R.bool.config_dreamsSupported)) { @@ -815,7 +854,23 @@ public class DisplaySettings extends SettingsPreferenceFragment implements if (!isCameraGestureAvailable(context.getResources())) { result.add(KEY_CAMERA_GESTURE); } + if (!hardware.isSupported(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { + result.add(KEY_HIGH_TOUCH_SENSITIVITY); + } return result; } }; + + public static void restore(Context context) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + final CMHardwareManager hardware = CMHardwareManager.getInstance(context); + if (hardware.isSupported(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { + final boolean enabled = prefs.getBoolean(KEY_HIGH_TOUCH_SENSITIVITY, + hardware.get(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)); + CMSettings.System.putInt(context.getContentResolver(), + CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE, + enabled ? 1 : 0); + } + } + } diff --git a/src/com/android/settings/DreamSettings.java b/src/com/android/settings/DreamSettings.java index 8137cd4..8431721 100644 --- a/src/com/android/settings/DreamSettings.java +++ b/src/com/android/settings/DreamSettings.java @@ -307,7 +307,7 @@ public class DreamSettings extends SettingsPreferenceFragment implements ((TextView) row.findViewById(android.R.id.title)).setText(dreamInfo.caption); // bind radio button - RadioButton radioButton = (RadioButton) row.findViewById(android.R.id.button1); + RadioButton radioButton = (RadioButton) row.findViewById(R.id.radio); radioButton.setChecked(dreamInfo.isActive); radioButton.setOnTouchListener(new OnTouchListener() { @Override @@ -321,7 +321,7 @@ public class DreamSettings extends SettingsPreferenceFragment implements View settingsDivider = row.findViewById(R.id.divider); settingsDivider.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); - ImageView settingsButton = (ImageView) row.findViewById(android.R.id.button2); + ImageView settingsButton = (ImageView) row.findViewById(R.id.settings); settingsButton.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); settingsButton.setAlpha(dreamInfo.isActive ? 1f : Utils.DISABLED_ALPHA); settingsButton.setEnabled(dreamInfo.isActive); @@ -337,8 +337,7 @@ public class DreamSettings extends SettingsPreferenceFragment implements private View createDreamInfoRow(ViewGroup parent) { final View row = mInflater.inflate(R.layout.dream_info_row, parent, false); - final View header = row.findViewById(android.R.id.widget_frame); - header.setOnClickListener(new OnClickListener(){ + row.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { v.setPressed(true); diff --git a/src/com/android/settings/HelpUtils.java b/src/com/android/settings/HelpUtils.java index 3c36edb..1b6cbf7 100644 --- a/src/com/android/settings/HelpUtils.java +++ b/src/com/android/settings/HelpUtils.java @@ -24,6 +24,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources.Theme; import android.net.Uri; +import android.provider.Settings.Global; import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; @@ -90,6 +91,9 @@ public class HelpUtils { */ public static boolean prepareHelpMenuItem(final Activity activity, MenuItem helpMenuItem, String helpUriString, String backupContext) { + if (Global.getInt(activity.getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) { + return false; + } if (TextUtils.isEmpty(helpUriString)) { // The help url string is empty or null, so set the help menu item to be invisible. helpMenuItem.setVisible(false); @@ -123,6 +127,9 @@ public class HelpUtils { public static Intent getHelpIntent(Context context, String helpUriString, String backupContext) { + if (Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) { + return null; + } // Try to handle as Intent Uri, otherwise just treat as Uri. try { Intent intent = Intent.parseUri(helpUriString, diff --git a/src/com/android/settings/IccLockSettings.java b/src/com/android/settings/IccLockSettings.java index ff7c2bd..f4daceb 100644 --- a/src/com/android/settings/IccLockSettings.java +++ b/src/com/android/settings/IccLockSettings.java @@ -40,6 +40,7 @@ import android.widget.ListView; import android.widget.Toast; import com.android.internal.logging.MetricsLogger; +import com.android.internal.telephony.IccCardConstants.State; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.TelephonyIntents; @@ -222,11 +223,20 @@ public class IccLockSettings extends InstrumentedPreferenceActivity private void updatePreferences() { - mPinDialog.setEnabled(mPhone != null); - mPinToggle.setEnabled(mPhone != null); - if (mPhone != null) { + if (mPhone.getIccCard().getState() != State.READY) { + // if SIM State is NOT READY, it is not possible to interact with UICC app + // for enabling/disabling PIN so disable PIN options. + mPinToggle.setEnabled(false); + mPinDialog.setEnabled(false); + } else { + mPinToggle.setEnabled(true); + mPinDialog.setEnabled(true); + } mPinToggle.setChecked(mPhone.getIccCard().getIccLockEnabled()); + } else { + mPinDialog.setEnabled(false); + mPinToggle.setEnabled(false); } } diff --git a/src/com/android/settings/ScreenColorSettings.java b/src/com/android/settings/ScreenColorSettings.java deleted file mode 100644 index 4d4caaa..0000000 --- a/src/com/android/settings/ScreenColorSettings.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - Copyright (c) 2014, The Linux Foundation. All Rights Reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package com.android.settings; - -import java.io.FileNotFoundException; -import java.io.InputStream; - -import android.app.ActionBar; -import android.app.Activity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.drawable.BitmapDrawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.Window; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.ListView; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.PopupMenu; -import android.widget.RadioButton; -import android.widget.PopupMenu.OnMenuItemClickListener; -import android.widget.RadioGroup; -import android.widget.RelativeLayout; -import android.widget.SeekBar; -import android.widget.TextView; -import android.widget.PopupWindow; - -import com.android.display.IPPService; - -public class ScreenColorSettings extends Activity { - private final static String TAG = "ScreenColorSettings"; - private final static boolean DEBUG = false; - - private final static int MODE_STANDARD = 0; - private final static int MODE_VIVID = 1; - private final static int MODE_CUSTOM = 2; - - private static final String COLOR_MODE = "mode"; - private static final String COLOR_HUE = "hue"; - private static final String COLOR_SATURATION = "saturation"; - private static final String COLOR_INTENSITY = "intensity"; - private static final String COLOR_CONTRAST = "contrast"; - - private static final String PREVIEW_STRING_NAME = "screencolor_preview_name"; - - private int mMode = 0; - private IPPService mPPService = null; - private PPServiceConnection mPPServiceConn = null; - private SharedPreferences mSharedPreference; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - initPPService(); - getWindow().requestFeature(Window.FEATURE_ACTION_BAR); - setContentView(R.layout.screencolor_settings); - - ListView listView = (ListView)findViewById(R.id.mode_list); - listView.setBackgroundColor(R.color.screencolor_background); - mSharedPreference = getSharedPreferences(PREVIEW_STRING_NAME, Context.MODE_PRIVATE); - mMode = mSharedPreference.getInt(COLOR_MODE, 0); - setScreenColorMode(mMode); - String[] list = getResources().getStringArray(R.array.screen_color_setting); - ColorModeAdaper adapter = new ColorModeAdaper(this, - R.layout.screen_color_item, list); - listView.setAdapter(adapter); - } - - private class ColorModeAdaper extends ArrayAdapter<String> { - private int mResource; - private RelativeLayout mItemView; - - public ColorModeAdaper(Context context, int resource, String[] list) { - super(context, resource, list); - this.mResource = resource; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - String name = getItem(position); - if(convertView == null) { - mItemView = new RelativeLayout(getContext()); - LayoutInflater vi = (LayoutInflater)getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - vi.inflate(mResource, mItemView, true); - } else { - mItemView = (RelativeLayout) convertView; - } - ((TextView) mItemView.findViewById(android.R.id.title)).setText(name); - - RadioButton radioButton = (RadioButton) mItemView.findViewById(android.R.id.button1); - ImageView setting = (ImageView) mItemView.findViewById(android.R.id.button2); - if (mMode == position) { - radioButton.setChecked(true); - setting.setEnabled(true); - } else { - radioButton.setChecked(false); - setting.setEnabled(false); - } - - if (position != getCount()-1) { - ((ImageView) mItemView.findViewById(R.id.divider)).setVisibility(View.INVISIBLE); - setting.setVisibility(View.INVISIBLE); - } else { - setting.setOnClickListener(new OnClickListener () { - @Override - public void onClick(View v) { - Intent intent = new Intent(); - intent.setClass(ScreenColorSettings.this, CustomScreenColor.class); - startActivity(intent); - }}); - } - - View v = mItemView.findViewById(R.id.widget_frame); - v.setTag(position); - v.setOnClickListener(new OnClickListener () { - @Override - public void onClick(View v) { - int mode = (Integer)(v.getTag()); - setScreenColorMode(mode); - notifyDataSetChanged(); - }}); - return mItemView; - } - } - - private void initPPService() { - mPPServiceConn = new PPServiceConnection(); - String packetname = "com.qualcomm.display"; - String service = "com.qualcomm.display.PPService"; - Intent i = new Intent(IPPService.class.getName()); - - ComponentName component = new ComponentName(packetname, service); - i.setComponent(component); - - bindService(i, mPPServiceConn, Context.BIND_AUTO_CREATE); - } - - private class PPServiceConnection implements ServiceConnection { - - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - mPPService = IPPService.Stub.asInterface((IBinder) service); - if (DEBUG) Log.d(TAG, "onServiceConnected, service=" + mPPService); - try { - if (null != mPPService) { - mPPService.startPP(); - setScreenColorMode(mMode); - } - } catch (RemoteException e) { - Log.e(TAG, "startPP exception"); - } - } - - @Override - public void onServiceDisconnected(ComponentName name) { - if (null != mPPService) { - try { - mPPService.stopPP(); - } catch (RemoteException e) { - Log.e(TAG, "stopPP exception"); - } - } - mPPService = null; - } - - } - - private void setScreenColorMode(int mode) { - if (DEBUG) Log.i(TAG, "setScreenColorMode mode = " + mode); - int hue = 0; - int saturation = 0; - int intensity = 0; - int contrast = 0; - switch (mode) { - case MODE_STANDARD: - hue = 180; - saturation = 180; - intensity = 255; - contrast = 180; - break; - case MODE_VIVID: - hue = 180; - saturation = 210; - intensity = 255; - contrast = 180; - break; - case MODE_CUSTOM: - hue = mSharedPreference.getInt(COLOR_HUE, 180); - saturation = mSharedPreference.getInt(COLOR_SATURATION, 180); - intensity = mSharedPreference.getInt(COLOR_INTENSITY, 255); - contrast = mSharedPreference.getInt(COLOR_CONTRAST, 180); - break; - default: - break; - } - saveModeValue(mode); - updateHSCIValue(hue, saturation, intensity, contrast); - } - - private void updateHSCIValue(int hue, int saturation, int intensity, int contrast) { - try { - if (null != mPPService && mPPService.getPPStatus()) { - mPPService.updateHSIC(hue, saturation, intensity, contrast); - } - } catch (RemoteException e) { - Log.e(TAG, "updateHSIC exception"); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - unbindService(mPPServiceConn); - } - - private void saveModeValue(int mode) { - mMode = mode; - Editor editor = mSharedPreference.edit(); - editor.putInt(COLOR_MODE, mode); - editor.commit(); - } -} diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java index 8f2db6b..7db4a4e 100644 --- a/src/com/android/settings/SecuritySettings.java +++ b/src/com/android/settings/SecuritySettings.java @@ -31,6 +31,7 @@ import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; import android.os.Bundle; import android.os.PersistableBundle; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.preference.ListPreference; @@ -71,6 +72,7 @@ import java.util.ArrayList; import java.util.List; import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; +import static cyanogenmod.content.Intent.ACTION_OPEN_LIVE_LOCKSCREEN_SETTINGS; /** * Gesture lock pattern settings. @@ -124,6 +126,7 @@ public class SecuritySettings extends SettingsPreferenceFragment private static final String KEY_SMS_SECURITY_CHECK_PREF = "sms_security_check_limit"; private static final String KEY_GENERAL_CATEGORY = "general_category"; private static final String KEY_LIVE_LOCK_SCREEN = "live_lock_screen"; + private static final String KEY_LOCK_SCREEN_BLUR = CMSettings.Secure.LOCK_SCREEN_BLUR_ENABLED; // These switch preferences need special handling since they're not all stored in Settings. private static final String SWITCH_PREFERENCE_KEYS[] = { KEY_LOCK_AFTER_TIMEOUT, @@ -194,7 +197,7 @@ public class SecuritySettings extends SettingsPreferenceFragment Bundle extras = getActivity().getIntent().getExtras(); // Even uglier hack to make cts verifier expectations make sense. - if (extras.get(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS) != null && + if (extras != null && extras.get(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS) != null && extras.get(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SHORTCUT) == null) { mFilterType = TYPE_EXTERNAL_RESOLUTION; } @@ -347,13 +350,24 @@ public class SecuritySettings extends SettingsPreferenceFragment // Add live lock screen preference if supported PreferenceGroup generalCategory = (PreferenceGroup) root.findPreference(KEY_GENERAL_CATEGORY); - if (pm.hasSystemFeature(LIVE_LOCK_SCREEN_FEATURE) && generalCategory != null) { + if (pm.hasSystemFeature(LIVE_LOCK_SCREEN_FEATURE) && generalCategory != null && Utils.isUserOwner()) { + boolean moveToTop = getResources().getBoolean( + R.bool.config_showLiveLockScreenSettingsFirst); + + PreferenceGroup groupToAddTo = moveToTop ? root : generalCategory; Preference liveLockPreference = new Preference(getContext(), null); - liveLockPreference.setFragment(LiveLockScreenSettings.class.getCanonicalName()); - liveLockPreference.setOrder(0); - liveLockPreference.setTitle(R.string.live_lock_screen_title); - liveLockPreference.setSummary(R.string.live_lock_screen_summary); - generalCategory.addPreference(liveLockPreference); + liveLockPreference.setIntent(new Intent(ACTION_OPEN_LIVE_LOCKSCREEN_SETTINGS)); + liveLockPreference.setOrder(-1); + setLiveLockScreenPreferenceTitleAndSummary(liveLockPreference); + groupToAddTo.addPreference(liveLockPreference); + } + + // only show blur setting for devices that support it + boolean blurSupported = getResources().getBoolean( + com.android.internal.R.bool.config_ui_blur_enabled); + if (!blurSupported && generalCategory != null) { + Preference blurEnabledPref = generalCategory.findPreference(KEY_LOCK_SCREEN_BLUR); + if (blurEnabledPref != null) generalCategory.removePreference(blurEnabledPref); } } @@ -436,26 +450,34 @@ public class SecuritySettings extends SettingsPreferenceFragment updateSmsSecuritySummary(smsSecurityCheck); } - // Show password - mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD); - mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS); - - // Credential storage + // needed by Credential storage and Application install sections final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); - mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume() - if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { - Preference credentialStorageType = root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE); - final int storageSummaryRes = - mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware - : R.string.credential_storage_type_software; - credentialStorageType.setSummary(storageSummaryRes); - } else { - PreferenceGroup credentialsManager = (PreferenceGroup) - root.findPreference(KEY_CREDENTIALS_MANAGER); - credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS)); - credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL)); - credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE)); + // Both "Show password" and "Credential storage" options depend on having a KeyStore. + // However, KeyStore assumes that there's an android.security.keystore service around. + // Let's validate if it indeed exists here, to avoid breakage. + if (ServiceManager.getService("android.security.keystore") != null) { + // Show password + mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD); + mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS); + + // Credential storage + mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume() + + if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { + Preference credentialStorageType = root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE); + + final int storageSummaryRes = + mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware + : R.string.credential_storage_type_software; + credentialStorageType.setSummary(storageSummaryRes); + } else { + PreferenceGroup credentialsManager = (PreferenceGroup) + root.findPreference(KEY_CREDENTIALS_MANAGER); + credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS)); + credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL)); + credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE)); + } } // Application install @@ -868,6 +890,46 @@ public class SecuritySettings extends SettingsPreferenceFragment } /** + * Loads the title and summary for live lock screen preference. If an external package supports + * the {@link cyanogenmod.content.Intent#ACTION_OPEN_LIVE_LOCKSCREEN_SETTINGS} we attempt to + * load the title and summary from that package and use defaults if those cannot be loaded or + * no other package is found to support the action. + * @param pref + */ + private void setLiveLockScreenPreferenceTitleAndSummary(Preference pref) { + String title = getString(R.string.live_lock_screen_title); + String summary = getString(R.string.live_lock_screen_summary); + PackageManager pm = getPackageManager(); + List<ResolveInfo> infos = pm.queryIntentActivities( + new Intent(ACTION_OPEN_LIVE_LOCKSCREEN_SETTINGS), 0); + if (infos != null && infos.size() > 1) { + for (ResolveInfo info : infos) { + if (!getActivity().getPackageName().equals(info.activityInfo.packageName)) { + try { + final Context ctx = getActivity().createPackageContext( + info.activityInfo.packageName, 0); + final Resources res = ctx.getResources(); + int titleId = res.getIdentifier("live_lock_screen_title", "string", + info.activityInfo.packageName); + int summaryId = res.getIdentifier("live_lock_screen_summary", "string", + info.activityInfo.packageName); + if (titleId !=0 && summaryId != 0) { + title = res.getString(titleId); + summary = res.getString(summaryId); + } + } catch (PackageManager.NameNotFoundException e) { + /* ignore and use defaults */ + } + break; + } + } + } + + pref.setTitle(title); + pref.setSummary(summary); + } + + /** * For Search. Please keep it in sync when updating "createPreferenceHierarchy()" */ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = @@ -957,20 +1019,7 @@ public class SecuritySettings extends SettingsPreferenceFragment result.add(data); } - // Advanced - final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); - if (lockPatternUtils.isSecure(MY_USER_ID)) { - ArrayList<TrustAgentComponentInfo> agents = - getActiveTrustAgents(context.getPackageManager(), lockPatternUtils, - context.getSystemService(DevicePolicyManager.class)); - for (int i = 0; i < agents.size(); i++) { - final TrustAgentComponentInfo agent = agents.get(i); - data = new SearchIndexableRaw(context); - data.title = agent.title; - data.screenTitle = screenTitle; - result.add(data); - } - } + return result; } @@ -979,8 +1028,6 @@ public class SecuritySettings extends SettingsPreferenceFragment final List<String> keys = new ArrayList<String>(); LockPatternUtils lockPatternUtils = new LockPatternUtils(context); - // Add options for lock/unlock screen - int resId = getResIdForLockUnlockScreen(context, lockPatternUtils); // Do not display SIM lock for devices without an Icc card TelephonyManager tm = TelephonyManager.getDefault(); diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 0cfbfae..a52af29 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -123,7 +123,9 @@ public class Settings extends SettingsActivity { public static class BlacklistSettingsActivity extends SettingsActivity { /* empty */ } public static class ProfilesSettingsActivity extends SettingsActivity { /* empty */ } public static class ContributorsCloudActivity extends SettingsActivity { /* empty */ } - public static class SoundSettingsActivity extends SettingsActivity { /* empty */ } + public static class CMSoundSettingsActivity extends SettingsActivity { /* empty */ } public static class LockScreenSettingsActivity extends SettingsActivity { /* empty */ } + public static class LiveLockScreenSettingsActivity extends SettingsActivity { /* empty */ } public static class NotificationManagerActivity extends SettingsActivity { /* empty */ } + public static class WeatherProviderServicesActivity extends SettingsActivity { /* empty */ } } diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 332d9b3..d5c53a4 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -41,12 +41,14 @@ import android.nfc.Tag; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; +import android.provider.Settings.Global; import android.text.TextUtils; import android.transition.TransitionManager; import android.util.ArrayMap; @@ -83,6 +85,8 @@ import com.android.settings.blacklist.BlacklistSettings; import com.android.settings.bluetooth.BluetoothSettings; import com.android.settings.contributors.ContributorsCloudFragment; import com.android.settings.cyanogenmod.DisplayRotation; +import com.android.settings.cyanogenmod.LiveLockScreenSettings; +import com.android.settings.cyanogenmod.WeatherServiceSettings; import com.android.settings.dashboard.DashboardCategory; import com.android.settings.dashboard.DashboardSummary; import com.android.settings.dashboard.DashboardTile; @@ -136,6 +140,7 @@ import com.android.settings.wifi.SavedAccessPointsWifiSettings; import com.android.settings.wifi.WifiSettings; import com.android.settings.wifi.p2p.WifiP2pSettings; +import cyanogenmod.app.CMContextConstants; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -277,6 +282,7 @@ public class SettingsActivity extends Activity R.id.display_and_lights_settings, R.id.lockscreen_settings, R.id.notification_manager, + R.id.status_bar_settings, R.id.storage_settings, R.id.application_settings, R.id.battery_settings, @@ -294,7 +300,6 @@ public class SettingsActivity extends Activity R.id.home_settings, R.id.dashboard, R.id.privacy_settings_cyanogenmod, - R.id.button_settings }; private static final String[] ENTRY_FRAGMENTS = { @@ -375,7 +380,9 @@ public class SettingsActivity extends Activity BlacklistSettings.class.getName(), ProfilesSettings.class.getName(), ContributorsCloudFragment.class.getName(), - NotificationManagerSettings.class.getName() + NotificationManagerSettings.class.getName(), + LiveLockScreenSettings.class.getName(), + WeatherServiceSettings.class.getName() }; @@ -637,7 +644,7 @@ public class SettingsActivity extends Activity 1 /* one home activity by default */); } else { if (!mIsShowingDashboard) { - mDisplaySearch = true; + mDisplaySearch = Process.myUid() == Process.SYSTEM_UID; // UP will be shown only if it is a sub settings if (mIsShortcut) { mDisplayHomeAsUpEnabled = isSubSettings; @@ -1260,9 +1267,7 @@ public class SettingsActivity extends Activity DashboardTile tile = category.getTile(n); boolean removeTile = false; id = (int) tile.id; - if (id == R.id.operator_settings || id == R.id.manufacturer_settings - || id == R.id.device_specific_gesture_settings - || id == R.id.oclick) { + if (id == R.id.operator_settings || id == R.id.manufacturer_settings) { if (!Utils.updateTileToSpecificActivityFromMetaDataOrRemove(this, tile)) { removeTile = true; } @@ -1326,6 +1331,14 @@ public class SettingsActivity extends Activity if (!hasDeviceKeys) { removeTile = true; } + } else if (id == R.id.weather_settings) { + final boolean showWeatherMenu = getResources() + .getBoolean(R.bool.config_showWeatherMenu); + + if (!getPackageManager().hasSystemFeature( + CMContextConstants.Features.WEATHER_SERVICES) || !showWeatherMenu) { + removeTile = true; + } } if (UserHandle.MU_ENABLED && UserHandle.myUserId() != 0 @@ -1343,6 +1356,10 @@ public class SettingsActivity extends Activity } private void addExternalTiles(List<DashboardCategory> target) { + if (Global.getInt(getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) { + // Don't add external tiles until device is set up. + return; + } Map<Pair<String, String>, DashboardTile> addedCache = new ArrayMap<Pair<String, String>, DashboardTile>(); UserManager userManager = UserManager.get(this); diff --git a/src/com/android/settings/SubSettings.java b/src/com/android/settings/SubSettings.java index 13ead6e..2bf451e 100644 --- a/src/com/android/settings/SubSettings.java +++ b/src/com/android/settings/SubSettings.java @@ -36,4 +36,5 @@ public class SubSettings extends SettingsActivity { return true; } public static class BluetoothSubSettings extends SubSettings { /* empty */ } + public static class SecuritySubSettings extends SubSettings { /* empty */ } } diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index 92ad580..594dc68 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -170,6 +170,7 @@ public class TetherSettings extends SettingsPreferenceFragment } else { getPreferenceScreen().removePreference(mEnableWifiAp); getPreferenceScreen().removePreference(wifiApSettings); + getPreferenceScreen().removePreference(mHotspotInactivityTimeout); } if (!bluetoothAvailable) { diff --git a/src/com/android/settings/TrustAgentUtils.java b/src/com/android/settings/TrustAgentUtils.java index 109663a..7fed4ec 100644 --- a/src/com/android/settings/TrustAgentUtils.java +++ b/src/com/android/settings/TrustAgentUtils.java @@ -55,7 +55,7 @@ public class TrustAgentUtils { public static class TrustAgentComponentInfo { ComponentName componentName; - String title; + public String title; String summary; boolean disabledByAdministrator; } diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index 837c36c..49b93e6 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -73,6 +73,7 @@ import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Profile; import android.provider.ContactsContract.RawContacts; +import android.provider.Settings; import android.service.persistentdata.PersistentDataBlockManager; import android.telephony.ServiceState; import android.telephony.TelephonyManager; @@ -866,6 +867,9 @@ public final class Utils { if (BluetoothSettings.class.getName().equals(fragmentName)) { intent.setClass(context, SubSettings.BluetoothSubSettings.class); intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, true); + } else if (SecuritySettings.class.getName().equals(fragmentName)) { + intent.setClass(context, SubSettings.SecuritySubSettings.class); + intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, true); } else { intent.setClass(context, SubSettings.class); } @@ -1449,4 +1453,9 @@ public final class Utils { items.get(count - 1)); } } + + public static boolean isAirplaneModeEnabled(Context context) { + return Settings.Global.getInt(context.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) != 0; + } } diff --git a/src/com/android/settings/WifiCallingSettings.java b/src/com/android/settings/WifiCallingSettings.java index f4d143d..fe83dda 100644 --- a/src/com/android/settings/WifiCallingSettings.java +++ b/src/com/android/settings/WifiCallingSettings.java @@ -193,7 +193,7 @@ public class WifiCallingSettings extends SettingsPreferenceFragment if (!isWfcModeSupported()) { android.provider.Settings.Global.putInt(context.getContentResolver(), android.provider.Settings.Global.WFC_IMS_MODE, - ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY); + ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED); } // NOTE: Buttons will be enabled/disabled in mPhoneStateListener diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java index 27f6768..1dd5508 100644 --- a/src/com/android/settings/accessibility/AccessibilitySettings.java +++ b/src/com/android/settings/accessibility/AccessibilitySettings.java @@ -160,7 +160,7 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements @Override public void onChange(boolean selfChange, Uri uri) { loadInstalledServices(); - updateServicesPreferences(); + updateAllPreferences(); } }; diff --git a/src/com/android/settings/accessibility/SettingsContentObserver.java b/src/com/android/settings/accessibility/SettingsContentObserver.java index c3baec5..383f54c 100644 --- a/src/com/android/settings/accessibility/SettingsContentObserver.java +++ b/src/com/android/settings/accessibility/SettingsContentObserver.java @@ -32,6 +32,8 @@ abstract class SettingsContentObserver extends ContentObserver { Settings.Secure.ACCESSIBILITY_ENABLED), false, this); contentResolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES), false, this); + contentResolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED), false, this); } public void unregister(ContentResolver contentResolver) { diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java index 9528ec1..cd8d1b5 100644 --- a/src/com/android/settings/applications/AppInfoBase.java +++ b/src/com/android/settings/applications/AppInfoBase.java @@ -156,7 +156,7 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment @Override public void onRunningStateChanged(boolean running) { - // No op. + refreshUi(); } @Override diff --git a/src/com/android/settings/applications/AppOpsDetails.java b/src/com/android/settings/applications/AppOpsDetails.java index 12da8b8..1d4a684 100644 --- a/src/com/android/settings/applications/AppOpsDetails.java +++ b/src/com/android/settings/applications/AppOpsDetails.java @@ -16,6 +16,7 @@ package com.android.settings.applications; +import android.Manifest; import android.app.Activity; import android.app.AppOpsManager; import android.app.Fragment; @@ -28,7 +29,13 @@ import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.res.Resources; import android.graphics.drawable.Drawable; +import android.net.NetworkPolicyManager; import android.os.Bundle; +import android.os.IDeviceIdleController; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.util.ArraySet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -47,8 +54,13 @@ import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_DATA; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_WLAN; + public class AppOpsDetails extends InstrumentedFragment { static final String TAG = "AppOpsDetails"; @@ -61,6 +73,7 @@ public class AppOpsDetails extends InstrumentedFragment { private LayoutInflater mInflater; private View mRootView; private LinearLayout mOperationsSection; + private NetworkPolicyManager mPolicyManager; private final int MODE_ALLOWED = 0; private final int MODE_IGNORED = 1; @@ -137,6 +150,20 @@ public class AppOpsDetails extends InstrumentedFragment { Resources res = getActivity().getResources(); + final IDeviceIdleController iDeviceIdleController = IDeviceIdleController.Stub.asInterface( + ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); + List<String> allowInPowerSave; + if (iDeviceIdleController != null) { + try { + allowInPowerSave = Arrays.asList(iDeviceIdleController.getSystemPowerWhitelist()); + } catch (RemoteException e) { + Log.e(TAG, "couldn't get system power white list", e); + allowInPowerSave = new ArrayList<>(); + } + } else { + allowInPowerSave = new ArrayList<>(); + } + mOperationsSection.removeAllViews(); String lastPermGroup = ""; boolean isPlatformSigned = isPlatformSigned(); @@ -170,21 +197,40 @@ public class AppOpsDetails extends InstrumentedFragment { } catch (NameNotFoundException e) { } } - ((TextView)view.findViewById(R.id.op_name)).setText( - entry.getSwitchText(mState)); - ((TextView)view.findViewById(R.id.op_counts)).setText( - entry.getCountsText(res)); - ((TextView)view.findViewById(R.id.op_time)).setText( - entry.getTimeText(res, true)); Spinner sp = (Spinner) view.findViewById(R.id.spinnerWidget); - sp.setVisibility(View.INVISIBLE); + sp.setVisibility(View.GONE); Switch sw = (Switch) view.findViewById(R.id.switchWidget); - sw.setVisibility(View.INVISIBLE); + sw.setVisibility(View.GONE); final int switchOp = AppOpsManager.opToSwitch(firstOp.getOp()); int mode = mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(), entry.getPackageOps().getPackageName()); + + final TextView opNameText = (TextView) view.findViewById(R.id.op_name); + final TextView opCountText = (TextView) view.findViewById(R.id.op_counts); + final TextView opTimeText = (TextView) view.findViewById(R.id.op_time); + + opNameText.setText(entry.getSwitchText(mState)); + + if (switchOp == AppOpsManager.OP_WAKE_LOCK + && allowInPowerSave.contains(entry.getPackageOps().getPackageName())) { + // sooper special case; app is marked to be allowed in power save; it is + // probably critical to functionality, don't allow user to change it, because + // we'll ignore it either way + sw.setVisibility(View.VISIBLE); + sw.setChecked(true); + sw.setEnabled(false); + + opCountText.setVisibility(View.GONE); + opTimeText.setText(R.string.app_ops_disabled_by_optimization); + + continue; + } + + opCountText.setText(entry.getCountsText(res)); + opTimeText.setText(entry.getTimeText(res, true)); + sp.setSelection(modeToPosition(mode)); sp.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() { boolean firstMode = true; @@ -226,9 +272,53 @@ public class AppOpsDetails extends InstrumentedFragment { } } + if (UserHandle.isApp(mPackageInfo.applicationInfo.uid) && + mPm.checkPermission(Manifest.permission.INTERNET, + mPackageInfo.packageName) == PackageManager.PERMISSION_GRANTED) { + TextView internetCategory = (TextView) mInflater.inflate( + R.layout.preference_category_material, null); + internetCategory.setText(R.string.privacy_guard_internet_category); + mOperationsSection.addView(internetCategory); + + addInternetSwitch(POLICY_REJECT_ON_WLAN); + addInternetSwitch(POLICY_REJECT_ON_DATA); + } + return true; } + private void addInternetSwitch(final int policy) { + // Add internet category permissions + final View view = mInflater.inflate(R.layout.app_ops_details_item, + mOperationsSection, false); + mOperationsSection.addView(view); + + ((TextView)view.findViewById(R.id.op_name)).setText( + policy == POLICY_REJECT_ON_DATA ? R.string.restrict_app_cellular_title : + R.string.restrict_app_wlan_title); + view.findViewById(R.id.op_counts).setVisibility(View.INVISIBLE); + view.findViewById(R.id.op_time).setVisibility(View.INVISIBLE); + view.findViewById(R.id.spinnerWidget).setVisibility(View.GONE); + + Switch sw = (Switch) view.findViewById(R.id.switchWidget); + sw.setChecked((mPolicyManager.getUidPolicy( + mPackageInfo.applicationInfo.uid) & policy) != 0); + sw.setTag(policy); + sw.setVisibility(View.VISIBLE); + sw.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() { + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + if (isChecked) { + mPolicyManager.addUidPolicy(mPackageInfo.applicationInfo.uid, + policy); + } else { + mPolicyManager.removeUidPolicy(mPackageInfo.applicationInfo.uid, + policy); + } + } + }); + } + private void setIntentAndFinish(boolean finish, boolean appChanged) { Intent intent = new Intent(); intent.putExtra(ManageApplications.APP_CHG, appChanged); @@ -245,6 +335,7 @@ public class AppOpsDetails extends InstrumentedFragment { mPm = getActivity().getPackageManager(); mInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); mAppOps = (AppOpsManager)getActivity().getSystemService(Context.APP_OPS_SERVICE); + mPolicyManager = NetworkPolicyManager.from(getActivity()); retrieveAppEntry(); diff --git a/src/com/android/settings/applications/AppOpsSummary.java b/src/com/android/settings/applications/AppOpsSummary.java index be153de..4ec390d 100644 --- a/src/com/android/settings/applications/AppOpsSummary.java +++ b/src/com/android/settings/applications/AppOpsSummary.java @@ -26,11 +26,13 @@ import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; import android.content.SharedPreferences; +import android.os.Build; import android.os.Bundle; import android.preference.PreferenceFrameLayout; import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; +import android.util.Pair; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.Menu; @@ -61,36 +63,35 @@ public class AppOpsSummary extends InstrumentedFragment { private Activity mActivity; private SharedPreferences mPreferences; - CharSequence[] mPageNames; - - int mCurPos; - @Override protected int getMetricsCategory() { return MetricsLogger.APP_OPS_SUMMARY; } - class MyPagerAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener { - private AppOpsState.OpsTemplate[] mPageTemplates; + static class MyPagerAdapter extends FragmentPagerAdapter + implements ViewPager.OnPageChangeListener { + private List<Pair<CharSequence, AppOpsState.OpsTemplate>> mPageData; + private int mCurPos; - public MyPagerAdapter(FragmentManager fm, AppOpsState.OpsTemplate[] templates) { + public MyPagerAdapter(FragmentManager fm, + List<Pair<CharSequence, AppOpsState.OpsTemplate>> data) { super(fm); - mPageTemplates = templates; + mPageData = data; } @Override public Fragment getItem(int position) { - return new AppOpsCategory(mPageTemplates[position]); + return new AppOpsCategory(mPageData.get(position).second); } @Override public int getCount() { - return mPageTemplates.length; + return mPageData.size(); } @Override public CharSequence getPageTitle(int position) { - return mPageNames[position]; + return mPageData.get(position).first; } @Override @@ -132,21 +133,25 @@ public class AppOpsSummary extends InstrumentedFragment { mContentContainer = container; mRootView = rootView; - mPageNames = getResources().getTextArray(R.array.app_ops_categories_cm); + CharSequence[] pageNames = getResources().getTextArray(R.array.app_ops_categories_cm); + AppOpsState.OpsTemplate[] templates = AppOpsState.ALL_TEMPLATES; + assert(pageNames.length == templates.length); - int defaultTab = -1; + int specificTab = -1; Bundle bundle = getArguments(); if (bundle != null) { - defaultTab = Arrays.asList(mPageNames).indexOf(bundle.getString("appops_tab", "")); + specificTab = Arrays.asList(pageNames).indexOf(bundle.getString("appops_tab", "")); + } + + List<Pair<CharSequence, AppOpsState.OpsTemplate>> pageData = new ArrayList<>(); + for (int i = 0; i < pageNames.length; i++) { + pageData.add(Pair.create(pageNames[i], templates[i])); } + filterPageData(pageData, specificTab); mViewPager = (ViewPager) rootView.findViewById(R.id.pager); - mAdapter = new MyPagerAdapter(getChildFragmentManager(), - filterTemplates(AppOpsState.ALL_TEMPLATES)); + mAdapter = new MyPagerAdapter(getChildFragmentManager(), pageData); mViewPager.setAdapter(mAdapter); - if (defaultTab >= 0) { - mViewPager.setCurrentItem(defaultTab); - } mViewPager.setOnPageChangeListener(mAdapter); PagerTabStrip tabs = (PagerTabStrip) rootView.findViewById(R.id.tabs); @@ -169,16 +174,19 @@ public class AppOpsSummary extends InstrumentedFragment { return rootView; } - private AppOpsState.OpsTemplate[] filterTemplates(AppOpsState.OpsTemplate[] templates) { - List<AppOpsState.OpsTemplate> validTemplates = new ArrayList(templates.length); - for (AppOpsState.OpsTemplate template : templates) { - if (template == AppOpsState.SU_TEMPLATE - && !DevelopmentSettings.isRootForAppsEnabled()) { - continue; + private void filterPageData(List<Pair<CharSequence, AppOpsState.OpsTemplate>> data, int tab) { + if (tab >= 0 && tab < data.size()) { + Pair<CharSequence, AppOpsState.OpsTemplate> item = data.get(tab); + data.clear(); + data.add(item); + } else if (!DevelopmentSettings.isRootForAppsEnabled()) { + for (Pair<CharSequence, AppOpsState.OpsTemplate> item : data) { + if (item.second == AppOpsState.SU_TEMPLATE) { + data.remove(item); + return; + } } - validTemplates.add(template); } - return validTemplates.toArray(new AppOpsState.OpsTemplate[0]); } private boolean shouldShowUserApps() { @@ -186,7 +194,8 @@ public class AppOpsSummary extends InstrumentedFragment { } private boolean shouldShowSystemApps() { - return mPreferences.getBoolean("show_system_apps", true); + return mPreferences.getBoolean("show_system_apps", true) && + mActivity.getResources().getBoolean(R.bool.config_showBuiltInAppsForPG); } @Override @@ -204,7 +213,11 @@ public class AppOpsSummary extends InstrumentedFragment { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.appops_manager, menu); menu.findItem(R.id.show_user_apps).setChecked(shouldShowUserApps()); - menu.findItem(R.id.show_system_apps).setChecked(shouldShowSystemApps()); + if (!mActivity.getResources().getBoolean(R.bool.config_showBuiltInAppsForPG)) { + menu.removeItem(R.id.show_system_apps); + } else { + menu.findItem(R.id.show_system_apps).setChecked(shouldShowSystemApps()); + } } private void resetCounters() { diff --git a/src/com/android/settings/applications/ExpandedDesktopExtraPrefs.java b/src/com/android/settings/applications/ExpandedDesktopExtraPrefs.java index f709a98..f729aa3 100644 --- a/src/com/android/settings/applications/ExpandedDesktopExtraPrefs.java +++ b/src/com/android/settings/applications/ExpandedDesktopExtraPrefs.java @@ -23,10 +23,12 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.os.RemoteException; import android.preference.ListPreference; import android.preference.Preference; import android.provider.Settings; import android.view.WindowManager; +import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicyControl; import com.android.internal.logging.MetricsLogger; @@ -55,9 +57,17 @@ public class ExpandedDesktopExtraPrefs extends SettingsPreferenceFragment @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.expanded_desktop_prefs); - mExpandedDesktopStyle = getExpandedDesktopStyle(); - createPreferences(); + boolean hasNavigationBar = true; + try { + hasNavigationBar = WindowManagerGlobal.getWindowManagerService().hasNavigationBar(); + } catch (RemoteException e) { + // Do nothing + } + if (hasNavigationBar) { + addPreferencesFromResource(R.xml.expanded_desktop_prefs); + mExpandedDesktopStyle = getExpandedDesktopStyle(); + createPreferences(); + } } @Override diff --git a/src/com/android/settings/applications/ExpandedDesktopPreferenceFragment.java b/src/com/android/settings/applications/ExpandedDesktopPreferenceFragment.java index af8bf10..4f4f234 100644 --- a/src/com/android/settings/applications/ExpandedDesktopPreferenceFragment.java +++ b/src/com/android/settings/applications/ExpandedDesktopPreferenceFragment.java @@ -106,8 +106,6 @@ public class ExpandedDesktopPreferenceFragment extends SettingsPreferenceFragmen } mAllPackagesAdapter = new AllPackagesAdapter(getActivity()); - mAllPackagesAdapter.notifyDataSetChanged(); - setHasOptionsMenu(true); } @@ -260,7 +258,7 @@ public class ExpandedDesktopPreferenceFragment extends SettingsPreferenceFragmen @Override public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> entries) { - handleAppEntries(entries); + rebuild(); } @Override @@ -282,7 +280,7 @@ public class ExpandedDesktopPreferenceFragment extends SettingsPreferenceFragmen @Override public void onLoadEntriesCompleted() { - + rebuild(); } private void handleAppEntries(List<ApplicationsState.AppEntry> entries) { @@ -335,6 +333,7 @@ public class ExpandedDesktopPreferenceFragment extends SettingsPreferenceFragmen mActivityFilter, ApplicationsState.ALPHA_COMPARATOR); if (newEntries != null) { handleAppEntries(newEntries); + mAllPackagesAdapter.notifyDataSetChanged(); } } diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index 4d29c73..ef3788c 100755 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -413,8 +413,8 @@ public class InstalledAppDetails extends AppInfoBase mUpdatedSysApp = (mAppEntry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; menu.findItem(UNINSTALL_UPDATES).setVisible(mUpdatedSysApp && !mAppControlRestricted); - menu.findItem(OPEN_PROTECTED_APPS).setVisible(mPackageInfo.applicationInfo.protect); - + menu.findItem(OPEN_PROTECTED_APPS).setVisible(mPackageInfo != null && + mPackageInfo.applicationInfo != null && mPackageInfo.applicationInfo.protect); } @Override @@ -709,6 +709,10 @@ public class InstalledAppDetails extends AppInfoBase } private void checkForceStop() { + if (getActivity() == null || getActivity().isFinishing()) { + return; + } + if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) { // User can't force stop device admin. updateForceStopButton(false); @@ -984,6 +988,13 @@ public class InstalledAppDetails extends AppInfoBase mPm.setApplicationEnabledSetting(mInfo.packageName, mState, 0); return null; } + + @Override + protected void onPostExecute(Object o) { + if (mActivity.get() != null) { + mActivity.get().refreshUi(); + } + } } private final LoaderCallbacks<ChartData> mDataCallbacks = new LoaderCallbacks<ChartData>() { @@ -1008,7 +1019,9 @@ public class InstalledAppDetails extends AppInfoBase private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - updateForceStopButton(getResultCode() != Activity.RESULT_CANCELED); + if (getActivity() != null && !getActivity().isDestroyed()) { + updateForceStopButton(getResultCode() != Activity.RESULT_CANCELED); + } } }; diff --git a/src/com/android/settings/applications/LockPatternActivity.java b/src/com/android/settings/applications/LockPatternActivity.java index 9ab51b5..05d30ec 100644 --- a/src/com/android/settings/applications/LockPatternActivity.java +++ b/src/com/android/settings/applications/LockPatternActivity.java @@ -46,9 +46,20 @@ public class LockPatternActivity extends Activity implements OnNotifyAccountRese public static final String PATTERN_LOCK_PROTECTED_APPS = "pattern_lock_protected_apps"; public static final String RECREATE_PATTERN = "recreate_pattern_lock"; + private static final String STATE_IS_ACCOUNT_VIEW = "isAccountView"; + private static final String STATE_CONTINUE_ENABLED = "continueEnabled"; + private static final String STATE_CONFIRMING = "confirming"; + private static final String STATE_RETRY_PATTERN = "retrypattern"; + private static final String STATE_RETRY = "retry"; + private static final String STATE_PATTERN_HASH = "pattern_hash"; + private static final String STATE_CREATE = "create"; + + private static String TIMEOUT_PREF_KEY = "retry_timeout"; + private static final int MIN_PATTERN_SIZE = 4; private static final int MAX_PATTERN_RETRY = 5; private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000; + private static final long FAILED_ATTEMPT_RETRY = 30; private static final int MENU_RESET = 0; @@ -68,6 +79,7 @@ public class LockPatternActivity extends Activity implements OnNotifyAccountRese boolean mRetryPattern = true; boolean mConfirming = false; boolean mFingerPrintSetUp = false; + boolean mRetryLocked = false; private FingerprintManager mFingerprintManager; private FingerprintUiHelper mFingerPrintUiHelper; @@ -137,18 +149,49 @@ public class LockPatternActivity extends Activity implements OnNotifyAccountRese @Override public boolean onCreateOptionsMenu(Menu menu) { menu.clear(); - if (!mCreate) { - menu.add(0, MENU_RESET, 0, R.string.lockpattern_reset_button) - .setIcon(R.drawable.ic_lockscreen_ime_white) - .setAlphabeticShortcut('r') - .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | - MenuItem.SHOW_AS_ACTION_WITH_TEXT); - mItem = menu.findItem(0); + menu.add(0, MENU_RESET, 0, R.string.lockpattern_reset_button) + .setIcon(R.drawable.ic_lockscreen_ime_white) + .setAlphabeticShortcut('r') + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | + MenuItem.SHOW_AS_ACTION_WITH_TEXT); + mItem = menu.findItem(0); + if (mRetryLocked) { + mItem.setIcon(R.drawable.ic_settings_lockscreen_white); } + return true; } @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(STATE_IS_ACCOUNT_VIEW, mAccountView.getVisibility() == View.VISIBLE); + outState.putBoolean(STATE_CONTINUE_ENABLED, mContinue.isEnabled()); + outState.putBoolean(STATE_CONFIRMING, mConfirming); + outState.putBoolean(STATE_RETRY_PATTERN, mRetryPattern); + outState.putInt(STATE_RETRY, mRetry); + outState.putByteArray(STATE_PATTERN_HASH, mPatternHash); + outState.putBoolean(STATE_CREATE, mCreate); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + if (savedInstanceState.getBoolean(STATE_IS_ACCOUNT_VIEW)) { + switchToAccount(); + } else { + switchToPattern(false); + mPatternHash = savedInstanceState.getByteArray(STATE_PATTERN_HASH); + mConfirming = savedInstanceState.getBoolean(STATE_CONFIRMING); + mRetryPattern = savedInstanceState.getBoolean(STATE_RETRY_PATTERN); + mRetry = savedInstanceState.getInt(STATE_RETRY); + mCreate = savedInstanceState.getBoolean(STATE_CREATE); + mContinue.setEnabled(savedInstanceState.getBoolean(STATE_CONTINUE_ENABLED, + mContinue.isEnabled())); + } + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_RESET: @@ -173,6 +216,9 @@ public class LockPatternActivity extends Activity implements OnNotifyAccountRese } private void switchToPattern(boolean reset) { + if (isRetryLocked()) { + return; + } if (reset) { resetPatternState(false); } @@ -188,7 +234,9 @@ public class LockPatternActivity extends Activity implements OnNotifyAccountRese private void switchToAccount() { mPatternLockHeader.setText(getResources() .getString(R.string.lockpattern_settings_reset_summary)); - mItem.setIcon(R.drawable.ic_settings_lockscreen_white); + if (mItem != null) { + mItem.setIcon(R.drawable.ic_settings_lockscreen_white); + } mAccountView.setVisibility(View.VISIBLE); mLockPatternView.setVisibility(View.GONE); } @@ -213,7 +261,6 @@ public class LockPatternActivity extends Activity implements OnNotifyAccountRese resetPatternState(false); //Setup Pattern Lock View - mLockPatternView.setSaveEnabled(false); mLockPatternView.setFocusable(false); mLockPatternView.setOnPatternListener(new UnlockPatternListener()); @@ -340,10 +387,12 @@ public class LockPatternActivity extends Activity implements OnNotifyAccountRese mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS); if (mRetry >= MAX_PATTERN_RETRY) { + setPatternTimeout(); mLockPatternView.removeCallbacks(mCancelPatternRunnable); Toast.makeText(getApplicationContext(), getResources().getString( - R.string.lockpattern_too_many_failed_confirmation_attempts), + R.string.lockpattern_too_many_failed_confirmation_attempts, + FAILED_ATTEMPT_RETRY), Toast.LENGTH_SHORT).show(); switchToAccount(); } @@ -396,5 +445,22 @@ public class LockPatternActivity extends Activity implements OnNotifyAccountRese mPatternLockHeader.setText(getString(R.string.pa_pattern_or_fingerprint_header)); mFingerPrintUiHelper.startListening(); } + if (isRetryLocked()) { + invalidateOptionsMenu(); + switchToAccount(); + } + } + + private boolean isRetryLocked() { + long time = System.currentTimeMillis(); + SharedPreferences prefs = getSharedPreferences(getPackageName(), MODE_PRIVATE); + long retryTime = prefs.getLong(TIMEOUT_PREF_KEY, 0); + mRetryLocked = (time - retryTime) < (FAILED_ATTEMPT_RETRY * 1000); + return mRetryLocked; + } + + private void setPatternTimeout() { + SharedPreferences prefs = getSharedPreferences(getPackageName(), MODE_PRIVATE); + prefs.edit().putLong(TIMEOUT_PREF_KEY, System.currentTimeMillis()).apply(); } } diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java index 61c2ebb..5902fc2 100644 --- a/src/com/android/settings/applications/ManageApplications.java +++ b/src/com/android/settings/applications/ManageApplications.java @@ -87,7 +87,8 @@ import java.util.Comparator; * intent. */ public class ManageApplications extends InstrumentedFragment - implements OnItemClickListener, OnItemSelectedListener { + implements OnItemClickListener, OnItemSelectedListener, + ResetAppsHelper.ResetCompletedCallback { static final String TAG = "ManageApplications"; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -276,7 +277,7 @@ public class ManageApplications extends InstrumentedFragment mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value); - mResetAppsHelper = new ResetAppsHelper(getActivity()); + mResetAppsHelper = new ResetAppsHelper(getActivity(), this); } @@ -302,13 +303,6 @@ public class ManageApplications extends InstrumentedFragment lv.setItemsCanFocus(true); lv.setTextFilterEnabled(true); mListView = lv; - mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter); - if (savedInstanceState != null) { - mApplications.mHasReceivedLoadEntries = - savedInstanceState.getBoolean(EXTRA_HAS_ENTRIES, false); - } - mListView.setAdapter(mApplications); - mListView.setRecyclerListener(mApplications); Utils.prepareCustomPreferencesList(container, mRootView, mListView, false); } @@ -319,8 +313,6 @@ public class ManageApplications extends InstrumentedFragment ((PreferenceFrameLayout.LayoutParams) mRootView.getLayoutParams()).removeBorders = true; } - createHeader(); - mResetAppsHelper.onRestoreInstanceState(savedInstanceState); return mRootView; @@ -365,6 +357,14 @@ public class ManageApplications extends InstrumentedFragment FrameLayout pinnedHeader = (FrameLayout) mRootView.findViewById(R.id.pinned_header); AppHeader.createAppHeader(getActivity(), null, mVolumeName, null, pinnedHeader); } + mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter); + if (savedInstanceState != null) { + mApplications.mHasReceivedLoadEntries = + savedInstanceState.getBoolean(EXTRA_HAS_ENTRIES, false); + } + mListView.setAdapter(mApplications); + mListView.setRecyclerListener(mApplications); + createHeader(); } private int getDefaultFilter() { @@ -538,9 +538,11 @@ public class ManageApplications extends InstrumentedFragment } mOptionsMenu.findItem(R.id.advanced).setVisible(mListType == LIST_TYPE_MAIN); - mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(mListType == LIST_TYPE_STORAGE + mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible( + (mListType == LIST_TYPE_STORAGE || mListType == LIST_TYPE_MAIN) && mSortOrder != R.id.sort_order_alpha); - mOptionsMenu.findItem(R.id.sort_order_size).setVisible(mListType == LIST_TYPE_STORAGE + mOptionsMenu.findItem(R.id.sort_order_size).setVisible( + (mListType == LIST_TYPE_STORAGE || mListType == LIST_TYPE_MAIN) && mSortOrder != R.id.sort_order_size); mOptionsMenu.findItem(R.id.show_system).setVisible(!mShowSystem @@ -618,6 +620,14 @@ public class ManageApplications extends InstrumentedFragment mFilterAdapter.setFilterEnabled(FILTER_APPS_DISABLED, hasDisabledApps); } + @Override + public void onResetCompleted() { + /* mExtraInfoBridge can be null when doing reset app preference without + * any changes on apps */ + if (mApplications.mExtraInfoBridge != null) + mApplications.mExtraInfoBridge.onPackageListChanged(); + } + static class FilterSpinnerAdapter extends ArrayAdapter<CharSequence> { private final ManageApplications mManageApplications; @@ -877,7 +887,8 @@ public class ManageApplications extends InstrumentedFragment Utils.handleLoadingContainer(mManageApplications.mLoadingContainer, mManageApplications.mListContainer, true, true); } - if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) { + if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS + || mManageApplications.mListType == LIST_TYPE_STORAGE) { // No enabled or disabled filters for usage access. return; } diff --git a/src/com/android/settings/applications/ProtectedAppsActivity.java b/src/com/android/settings/applications/ProtectedAppsActivity.java index a1c6cd5..7156c92 100644 --- a/src/com/android/settings/applications/ProtectedAppsActivity.java +++ b/src/com/android/settings/applications/ProtectedAppsActivity.java @@ -56,6 +56,7 @@ public class ProtectedAppsActivity extends Activity { private static final int REQ_RESET_PATTERN = 2; private static final String NEEDS_UNLOCK = "needs_unlock"; + private static final String TARGET_INTENT = "target_intent"; private ListView mListView; @@ -71,6 +72,7 @@ public class ProtectedAppsActivity extends Activity { private boolean mWaitUserAuth = false; private boolean mUserIsAuth = false; private Intent mTargetIntent; + private int mOrientation; private HashSet<ComponentName> mProtectedApps = new HashSet<ComponentName>(); @@ -100,24 +102,28 @@ public class ProtectedAppsActivity extends Activity { if (savedInstanceState != null) { mUserIsAuth = savedInstanceState.getBoolean(NEEDS_UNLOCK); - } - - if (!mUserIsAuth) { - // Require unlock - Intent lockPattern = new Intent(this, LockPatternActivity.class); - startActivityForResult(lockPattern, REQ_ENTER_PATTERN); + mTargetIntent = savedInstanceState.getParcelable(TARGET_INTENT); } else { - //LAUNCH - if (mTargetIntent != null) { - launchTargetActivityInfoAndFinish(); + if (!mUserIsAuth) { + // Require unlock + mWaitUserAuth = true; + Intent lockPattern = new Intent(this, LockPatternActivity.class); + startActivityForResult(lockPattern, REQ_ENTER_PATTERN); + } else { + //LAUNCH + if (mTargetIntent != null) { + launchTargetActivityInfoAndFinish(); + } } } + mOrientation = getResources().getConfiguration().orientation; } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(NEEDS_UNLOCK, mUserIsAuth); + outState.putParcelable(TARGET_INTENT, mTargetIntent); } @Override @@ -164,8 +170,10 @@ public class ProtectedAppsActivity extends Activity { public void onPause() { super.onPause(); - // Don't stick around - if (mWaitUserAuth && !mUserIsAuth) { + // Close this app to prevent unauthorized access when + // 1) not waiting for authorization and + // 2) there is no portrait/landscape mode switching + if (!mWaitUserAuth && (mOrientation == getResources().getConfiguration().orientation)) { finish(); } } @@ -178,7 +186,7 @@ public class ProtectedAppsActivity extends Activity { protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQ_ENTER_PATTERN: - mWaitUserAuth = true; + mWaitUserAuth = false; switch (resultCode) { case RESULT_OK: //Nothing to do, proceed! @@ -194,7 +202,7 @@ public class ProtectedAppsActivity extends Activity { } break; case REQ_RESET_PATTERN: - mWaitUserAuth = true; + mWaitUserAuth = false; mUserIsAuth = false; } } @@ -241,7 +249,7 @@ public class ProtectedAppsActivity extends Activity { } private void resetLock() { - mWaitUserAuth = false; + mWaitUserAuth = true; Intent lockPattern = new Intent(LockPatternActivity.RECREATE_PATTERN, null, this, LockPatternActivity.class); startActivityForResult(lockPattern, REQ_RESET_PATTERN); diff --git a/src/com/android/settings/applications/ResetAppsHelper.java b/src/com/android/settings/applications/ResetAppsHelper.java index ad2ea02..2d0f671 100644 --- a/src/com/android/settings/applications/ResetAppsHelper.java +++ b/src/com/android/settings/applications/ResetAppsHelper.java @@ -49,10 +49,11 @@ public class ResetAppsHelper implements DialogInterface.OnClickListener, private final NetworkPolicyManager mNpm; private final AppOpsManager mAom; private final Context mContext; + private final ResetCompletedCallback mResetCompletedCallback; private AlertDialog mResetDialog; - public ResetAppsHelper(Context context) { + public ResetAppsHelper(Context context, ResetCompletedCallback callback) { mContext = context; mPm = context.getPackageManager(); mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); @@ -60,6 +61,7 @@ public class ResetAppsHelper implements DialogInterface.OnClickListener, ServiceManager.getService(Context.NOTIFICATION_SERVICE)); mNpm = NetworkPolicyManager.from(context); mAom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + mResetCompletedCallback = callback; } public void onRestoreInstanceState(Bundle savedInstanceState) { @@ -139,7 +141,12 @@ public class ResetAppsHelper implements DialogInterface.OnClickListener, mNpm.setUidPolicy(uid, POLICY_NONE); } } + mResetCompletedCallback.onResetCompleted(); } }); } + + public interface ResetCompletedCallback { + public void onResetCompleted(); + } } diff --git a/src/com/android/settings/blacklist/EntryEditDialogFragment.java b/src/com/android/settings/blacklist/EntryEditDialogFragment.java index 6a387bc..11c9909 100644 --- a/src/com/android/settings/blacklist/EntryEditDialogFragment.java +++ b/src/com/android/settings/blacklist/EntryEditDialogFragment.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; +import android.app.FragmentManager; import android.content.ContentUris; import android.content.Context; import android.content.DialogInterface; @@ -37,14 +38,26 @@ import android.text.method.DialerKeyListener; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; +import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageButton; +import android.widget.Spinner; import android.widget.Toast; import com.android.internal.telephony.util.BlacklistUtils; import com.android.settings.R; +import com.google.i18n.phonenumbers.PhoneNumberUtil; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; public class EntryEditDialogFragment extends DialogFragment implements TextWatcher, DialogInterface.OnClickListener { @@ -54,6 +67,7 @@ public class EntryEditDialogFragment extends DialogFragment private CheckBox mBlockCalls; private CheckBox mBlockMessages; private Button mOkButton; + private Spinner mCountryCode; private static final String[] BLACKLIST_PROJECTION = { Blacklist.NUMBER, Blacklist.PHONE_MODE, Blacklist.MESSAGE_MODE @@ -72,6 +86,9 @@ public class EntryEditDialogFragment extends DialogFragment private static final String STATE_PHONE = "phone"; private static final String STATE_MESSAGE = "message"; private static final String STATE_EDIT_ENABLED = "edit_enabled"; + private static final String STATE_COUNTRY_CODE = "edit_country_code"; + + private static final String DELETE_CONFIRM_FRAGMENT_TAG = "delete_confirm"; public static EntryEditDialogFragment newInstance(long id) { Bundle args = new Bundle(); @@ -114,9 +131,11 @@ public class EntryEditDialogFragment extends DialogFragment neutralButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - EntryEditDialogFragment parent = EntryEditDialogFragment.this; - DialogFragment confirm = DeleteConfirmationFragment.newInstance(parent); - confirm.show(getFragmentManager(), "delete_confirm"); + FragmentManager fragMan = getChildFragmentManager(); + if (fragMan.findFragmentByTag(DELETE_CONFIRM_FRAGMENT_TAG) == null) { + DeleteConfirmationFragment.newInstance() + .show(fragMan, DELETE_CONFIRM_FRAGMENT_TAG); + } } }); @@ -142,6 +161,55 @@ public class EntryEditDialogFragment extends DialogFragment return getArguments().getLong("id", -1); } + private static String getLocaleCountry() { + final String country = Locale.getDefault().getCountry(); + if (TextUtils.isEmpty(country)) { + return null; + } + return country.toUpperCase(); + } + + private void populateCountryCodes(View view, Bundle savedState) { + PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); + // Get all supported country codes + Set<String> countryCodes = new HashSet<String>(); + for (String region : phoneUtil.getSupportedRegions()) { + countryCodes.add(String.valueOf(phoneUtil.getCountryCodeForRegion(region))); + } + List<String> entries = new ArrayList<String>(countryCodes); + Collections.sort(entries, new Comparator<String>() { + @Override + public int compare(String lhs, String rhs) { + return Integer.parseInt(lhs) - Integer.parseInt(rhs); + } + }); + + // If regex is supported, insert regex character + if (BlacklistUtils.isBlacklistRegexEnabled(getContext())) { + entries.add(0, "*"); + } + + // Set current country code as selected position + int selectedIndex = 0; + if (savedState == null) { + String country = getLocaleCountry(); + int currentCode = phoneUtil.getCountryCodeForRegion(country); + selectedIndex = entries.indexOf(String.valueOf(currentCode)); + } else { + selectedIndex = savedState.getInt(STATE_COUNTRY_CODE); + } + + ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getContext(), + android.R.layout.simple_spinner_item, entries); + arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mCountryCode.setAdapter(arrayAdapter); + mCountryCode.setSelection(selectedIndex); + + // Ensure we make the layout visible + View parent = view.findViewById(R.id.country_code_layout); + parent.setVisibility(View.VISIBLE); + } + private View createDialogView(long id, Bundle savedState) { final Activity activity = getActivity(); final LayoutInflater inflater = (LayoutInflater) @@ -153,6 +221,8 @@ public class EntryEditDialogFragment extends DialogFragment mEditText.setKeyListener(DialerKeyListener.getInstance()); mEditText.addTextChangedListener(this); + mCountryCode = (Spinner) view.findViewById(R.id.number_country_code); + mContactPickButton = (ImageButton) view.findViewById(R.id.select_contact); mContactPickButton.setOnClickListener(new View.OnClickListener() { @Override @@ -197,13 +267,20 @@ public class EntryEditDialogFragment extends DialogFragment mEditText.setEnabled(true); } + // Only populate country codes if new entry + if (id < 0 || savedState != null && mEditText.isEnabled()) { + populateCountryCodes(view, savedState); + } + // Mirror contacts selector to state of editText mContactPickButton.setEnabled(mEditText.isEnabled()); return view; } private void updateBlacklistEntry() { - String number = mEditText.getText().toString(); + String plusSymbol = getString(R.string.blacklist_country_code_plus); + String number = plusSymbol + mCountryCode.getSelectedItem() + + mEditText.getText().toString(); int flags = 0; int valid = BlacklistUtils.BLOCK_CALLS | BlacklistUtils.BLOCK_MESSAGES; if (mBlockCalls.isChecked()) { @@ -258,6 +335,7 @@ public class EntryEditDialogFragment extends DialogFragment dialogState.putBoolean(STATE_PHONE, mBlockCalls.isChecked()); dialogState.putBoolean(STATE_MESSAGE, mBlockMessages.isChecked()); dialogState.putBoolean(STATE_EDIT_ENABLED, mEditText.isEnabled()); + dialogState.putInt(STATE_COUNTRY_CODE, mCountryCode.getSelectedItemPosition()); state.putBundle(DIALOG_STATE, dialogState); } @@ -297,10 +375,9 @@ public class EntryEditDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { public DeleteConfirmationFragment() { } - public static DialogFragment newInstance(EntryEditDialogFragment parent) { - DialogFragment fragment = new DeleteConfirmationFragment(); - fragment.setTargetFragment(parent, 0); - return fragment; + + public static DialogFragment newInstance() { + return new DeleteConfirmationFragment(); } @Override @@ -317,7 +394,7 @@ public class EntryEditDialogFragment extends DialogFragment @Override public void onClick(DialogInterface dialog, int which) { - EntryEditDialogFragment parent = (EntryEditDialogFragment) getTargetFragment(); + EntryEditDialogFragment parent = (EntryEditDialogFragment) getParentFragment(); parent.onDeleteConfirmResult(which == DialogInterface.BUTTON_POSITIVE); } } diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java index 836ff12..93f6f5d 100644 --- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java +++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java @@ -284,7 +284,7 @@ public final class BluetoothDevicePreference extends Preference implements return R.drawable.ic_bt_headset_hfp; } } - return R.drawable.ic_settings_bluetooth; + return R.drawable.ic_bt_bluetooth; } private final BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() { diff --git a/src/com/android/settings/bluetooth/BluetoothEnabler.java b/src/com/android/settings/bluetooth/BluetoothEnabler.java index 7d6bebe..b6399b0 100644 --- a/src/com/android/settings/bluetooth/BluetoothEnabler.java +++ b/src/com/android/settings/bluetooth/BluetoothEnabler.java @@ -137,7 +137,6 @@ public final class BluetoothEnabler extends GenericSwitchToggle { setChecked(true); setEnabled(true); updateSearchIndex(true); - mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); break; case BluetoothAdapter.STATE_TURNING_OFF: setEnabled(false); diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java index d08cb34..37eebe7 100644 --- a/src/com/android/settings/bluetooth/BluetoothSettings.java +++ b/src/com/android/settings/bluetooth/BluetoothSettings.java @@ -140,7 +140,8 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - mInitialScanStarted = false; + /* Don't auto start scan if screen reconstructs due to frozen screen*/ + mInitialScanStarted = (savedInstanceState != null); mInitiateDiscoverable = true; mEmptyView = (TextView) getView().findViewById(android.R.id.empty); @@ -227,6 +228,10 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem if (mBluetoothEnabler != null) { mBluetoothEnabler.resume(getActivity()); } + if (mLocalAdapter != null) { + // enable page and inquiry scan + mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); + } super.onResume(); mInitiateDiscoverable = true; diff --git a/src/com/android/settings/cyanogenmod/BacklightTimeoutSeekBar.java b/src/com/android/settings/cyanogenmod/BacklightTimeoutSeekBar.java index 66a6d3f..66f1fdd 100644 --- a/src/com/android/settings/cyanogenmod/BacklightTimeoutSeekBar.java +++ b/src/com/android/settings/cyanogenmod/BacklightTimeoutSeekBar.java @@ -60,27 +60,6 @@ public class BacklightTimeoutSeekBar extends SeekBar { } @Override - public void setProgress(int progress) { - if (progress == 0) { - progress = getMax(); - } else { - progress--; - } - super.setProgress(progress); - } - - @Override - public int getProgress() { - int progress = super.getProgress(); - if (mUpdatingThumb) { - return progress; - } else if (progress == getMax()) { - return 0; - } - return progress + 1; - } - - @Override protected int updateTouchProgress(int lastProgress, int newProgress) { if (newProgress < mMax) { return newProgress; diff --git a/src/com/android/settings/cyanogenmod/BootReceiver.java b/src/com/android/settings/cyanogenmod/BootReceiver.java index 19c2794..406ccb1 100644 --- a/src/com/android/settings/cyanogenmod/BootReceiver.java +++ b/src/com/android/settings/cyanogenmod/BootReceiver.java @@ -23,12 +23,12 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; import com.android.settings.ButtonSettings; +import com.android.settings.DisplaySettings; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.contributors.ContributorsCloudFragment; import com.android.settings.hardware.VibratorIntensity; import com.android.settings.inputmethod.InputMethodAndLanguageSettings; -import com.android.settings.livedisplay.DisplayGamma; import com.android.settings.location.LocationSettings; import com.android.settings.DevelopmentSettings; @@ -42,9 +42,9 @@ public class BootReceiver extends BroadcastReceiver { if (!hasRestoredTunable(ctx)) { /* Restore the hardware tunable values */ ButtonSettings.restoreKeyDisabler(ctx); - DisplayGamma.restore(ctx); VibratorIntensity.restore(ctx); InputMethodAndLanguageSettings.restore(ctx); + DisplaySettings.restore(ctx); setRestoredTunable(ctx); } @@ -53,7 +53,7 @@ public class BootReceiver extends BroadcastReceiver { // Extract the contributors database ContributorsCloudFragment.extractContributorsCloudDatabase(ctx); - DevelopmentSettings.initializeUpdateRecoveryOption(); + DevelopmentSettings.initializeUpdateRecoveryOption(ctx); } private boolean hasRestoredTunable(Context context) { diff --git a/src/com/android/settings/cyanogenmod/ButtonBacklightBrightness.java b/src/com/android/settings/cyanogenmod/ButtonBacklightBrightness.java index a15a55c..7c63f34 100644 --- a/src/com/android/settings/cyanogenmod/ButtonBacklightBrightness.java +++ b/src/com/android/settings/cyanogenmod/ButtonBacklightBrightness.java @@ -252,7 +252,7 @@ public class ButtonBacklightBrightness extends DialogPreference implements if (buttonBrightness == 0) { setSummary(R.string.backlight_summary_disabled); } else if (timeout == 0) { - setSummary(R.string.backlight_summary_enabled); + setSummary(R.string.backlight_timeout_unlimited); } else { setSummary(getContext().getString(R.string.backlight_summary_enabled_with_timeout, getTimeoutString(timeout))); diff --git a/src/com/android/settings/cyanogenmod/LiveLockScreenSettings.java b/src/com/android/settings/cyanogenmod/LiveLockScreenSettings.java index 4ffcc31..17be5cd 100644 --- a/src/com/android/settings/cyanogenmod/LiveLockScreenSettings.java +++ b/src/com/android/settings/cyanogenmod/LiveLockScreenSettings.java @@ -52,9 +52,9 @@ import com.android.settings.SettingsActivity; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.Utils; import com.android.settings.widget.SwitchBar; +import cyanogenmod.app.LiveLockScreenManager; import cyanogenmod.externalviews.KeyguardExternalViewProviderService; import cyanogenmod.providers.CMSettings; -import org.cyanogenmod.internal.util.CmLockPatternUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -215,7 +215,7 @@ public class LiveLockScreenSettings extends SettingsPreferenceFragment implement ((TextView) row.findViewById(android.R.id.title)).setText(liveLockScreenInfo.caption); // bind radio button - RadioButton radioButton = (RadioButton) row.findViewById(android.R.id.button1); + RadioButton radioButton = (RadioButton) row.findViewById(R.id.radio); radioButton.setChecked(liveLockScreenInfo.isActive); radioButton.setOnTouchListener(new OnTouchListener() { @Override @@ -229,7 +229,7 @@ public class LiveLockScreenSettings extends SettingsPreferenceFragment implement View settingsDivider = row.findViewById(R.id.divider); settingsDivider.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); - ImageView settingsButton = (ImageView) row.findViewById(android.R.id.button2); + ImageView settingsButton = (ImageView) row.findViewById(R.id.settings); settingsButton.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); settingsButton.setAlpha(liveLockScreenInfo.isActive ? 1f : Utils.DISABLED_ALPHA); settingsButton.setEnabled(liveLockScreenInfo.isActive); @@ -246,8 +246,7 @@ public class LiveLockScreenSettings extends SettingsPreferenceFragment implement private View createLiveLockScreenInfoRow(ViewGroup parent) { final View row = mInflater.inflate(R.layout.live_lock_screen_info_row, parent, false); - final View header = row.findViewById(android.R.id.widget_frame); - header.setOnClickListener(new OnClickListener(){ + row.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { v.setPressed(true); @@ -316,12 +315,12 @@ public class LiveLockScreenSettings extends SettingsPreferenceFragment implement private final Context mContext; private final LiveLockScreenInfoComparator mComparator; - private CmLockPatternUtils mLockPatternUtils; + private LiveLockScreenManager mLLSM; public LiveLockScreenBackend(Context context) { mContext = context; mComparator = new LiveLockScreenInfoComparator(null); - mLockPatternUtils = new CmLockPatternUtils(context); + mLLSM = LiveLockScreenManager.getInstance(context); } public List<LiveLockScreenInfo> getLiveLockScreenInfos() { @@ -381,26 +380,20 @@ public class LiveLockScreenSettings extends SettingsPreferenceFragment implement } private void setBoolean(String key, boolean value) { - CMSettings.Secure.putInt(mContext.getContentResolver(), key, value ? 1 : 0); + mLLSM.setLiveLockScreenEnabled(value); } public void setActiveLiveLockScreen(ComponentName liveLockScreen) { logd("setActiveLiveLockScreen(%s)", liveLockScreen); - if (mLockPatternUtils == null) { - return; - } - try { - mLockPatternUtils.setThirdPartyKeyguard(liveLockScreen); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Failed to set active live lock screen to " + liveLockScreen, e); - } + cyanogenmod.app.LiveLockScreenInfo.Builder builder = + new cyanogenmod.app.LiveLockScreenInfo.Builder(); + builder.setComponent(liveLockScreen); + mLLSM.setDefaultLiveLockScreen(builder.build()); } public ComponentName getActiveLiveLockScreen() { - if (mLockPatternUtils == null) { - return null; - } - return mLockPatternUtils.getThirdPartyKeyguardComponent(); + cyanogenmod.app.LiveLockScreenInfo llsInfo = mLLSM.getDefaultLiveLockScreen(); + return llsInfo != null ? llsInfo.component : null; } public void launchSettings(LiveLockScreenInfo liveLockScreenInfo) { diff --git a/src/com/android/settings/cyanogenmod/LockscreenSettingsAlias.java b/src/com/android/settings/cyanogenmod/LockscreenSettingsAlias.java index d6ca06a..f89de89 100644 --- a/src/com/android/settings/cyanogenmod/LockscreenSettingsAlias.java +++ b/src/com/android/settings/cyanogenmod/LockscreenSettingsAlias.java @@ -16,8 +16,10 @@ package com.android.settings.cyanogenmod; +import android.app.admin.DevicePolicyManager; import com.android.internal.widget.LockPatternUtils; import com.android.settings.SecuritySettings; +import com.android.settings.TrustAgentUtils; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.SearchIndexableRaw; @@ -110,6 +112,21 @@ public class LockscreenSettingsAlias extends SecuritySettings { result.add(data); } + // Advanced + final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); + if (lockPatternUtils.isSecure(MY_USER_ID)) { + ArrayList<TrustAgentUtils.TrustAgentComponentInfo> agents = + getActiveTrustAgents(context.getPackageManager(), lockPatternUtils, + context.getSystemService(DevicePolicyManager.class)); + for (int i = 0; i < agents.size(); i++) { + final TrustAgentUtils.TrustAgentComponentInfo agent = agents.get(i); + data = new SearchIndexableRaw(context); + data.title = agent.title; + data.screenTitle = screenTitle; + result.add(data); + } + } + return result; } } diff --git a/src/com/android/settings/cyanogenmod/SpamList.java b/src/com/android/settings/cyanogenmod/SpamList.java index 184ca6c..b1a24a8 100644 --- a/src/com/android/settings/cyanogenmod/SpamList.java +++ b/src/com/android/settings/cyanogenmod/SpamList.java @@ -121,8 +121,7 @@ public class SpamList extends ListFragment { menu.add(0, MENU_NOTIFICATIONS, 0, R.string.volume_notification_description) .setIcon(R.drawable.ic_filter_notifications) .setAlphabeticShortcut('n') - .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | - MenuItem.SHOW_AS_ACTION_WITH_TEXT); + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); } @Override diff --git a/src/com/android/settings/cyanogenmod/WeatherServiceSettings.java b/src/com/android/settings/cyanogenmod/WeatherServiceSettings.java new file mode 100644 index 0000000..903af8b --- /dev/null +++ b/src/com/android/settings/cyanogenmod/WeatherServiceSettings.java @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.cyanogenmod; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.UserHandle; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Xml; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ListView; +import android.widget.RadioButton; +import android.widget.TextView; +import android.widget.Toast; +import com.android.internal.content.PackageMonitor; +import com.android.internal.os.BackgroundThread; +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.Utils; +import cyanogenmod.providers.CMSettings; +import cyanogenmod.providers.WeatherContract; +import cyanogenmod.weather.CMWeatherManager; +import cyanogenmod.weatherservice.WeatherProviderService; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import static org.cyanogenmod.internal.logging.CMMetricsLogger.WEATHER_SETTINGS; + +public class WeatherServiceSettings extends SettingsPreferenceFragment + implements Preference.OnPreferenceChangeListener { + + private Context mContext; + private Handler mHandler; + private static final String TAG = WeatherServiceSettings.class.getSimpleName(); + + private static final String PREFERENCE_GENERAL = "weather_general_settings"; + private static final String PREFERENCE_PROVIDERS = "weather_service_providers"; + private static final String PREFERENCE_TEMP_UNIT = "weather_temperature_unit"; + + private PreferenceCategory mGeneralSettingsCategory; + private PreferenceCategory mProvidersCategory; + private ListPreference mTemperatureUnit; + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mContext = activity; + mHandler = new Handler(mContext.getMainLooper()); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.weather_settings); + + final PreferenceScreen ps = getPreferenceScreen(); + mGeneralSettingsCategory = (PreferenceCategory) ps.findPreference(PREFERENCE_GENERAL); + mProvidersCategory = (PreferenceCategory) ps.findPreference(PREFERENCE_PROVIDERS); + mTemperatureUnit = (ListPreference) ps.findPreference(PREFERENCE_TEMP_UNIT); + mTemperatureUnit.setOnPreferenceChangeListener(this); + } + + @Override + protected int getMetricsCategory() { + return WEATHER_SETTINGS; + } + + @Override + public void onResume() { + super.onResume(); + updateAdapter(); + registerPackageMonitor(); + + mTemperatureUnit.setValue(String.valueOf(getSelectedTemperatureUnit(mContext))); + } + + @Override + public void onPause() { + super.onPause(); + unregisterPackageMonitor(); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + if (preference == mTemperatureUnit) { + CMSettings.Global.putInt(mContext.getContentResolver(), + CMSettings.Global.WEATHER_TEMPERATURE_UNIT, + Integer.valueOf((String) newValue)); + } + return true; + } + + private void registerPackageMonitor() { + mPackageMonitor.register(mContext, BackgroundThread.getHandler().getLooper(), + UserHandle.ALL, true); + } + + private void launchGetWeatherProviders() { + try { + startActivity(new Intent(Intent.ACTION_VIEW, + Uri.parse(getString(R.string.weather_settings_play_store_market_url))) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } catch (ActivityNotFoundException e) { + startActivity(new Intent(Intent.ACTION_VIEW, + Uri.parse(getString(R.string.weather_settings_play_store_http_url))) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + } + + private void unregisterPackageMonitor() { + mPackageMonitor.unregister(); + } + + private PackageMonitor mPackageMonitor = new PackageMonitor() { + @Override + public void onPackageAdded(String packageName, int uid) { + mHandler.post(new Runnable() { + @Override + public void run() { + updateAdapter(); + } + }); + } + + @Override + public void onPackageRemoved(String packageName, int uid) { + mHandler.post(new Runnable() { + @Override + public void run() { + updateAdapter(); + } + }); + } + }; + + private void updateAdapter() { + final PackageManager pm = getContext().getPackageManager(); + final Intent intent = new Intent(WeatherProviderService.SERVICE_INTERFACE); + List<ResolveInfo> resolveInfoList = pm.queryIntentServices(intent, + PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); + List<WeatherProviderServiceInfo> weatherProviderServiceInfos + = new ArrayList<>(resolveInfoList.size()); + ComponentName activeService = getEnabledWeatherServiceProvider(); + for (ResolveInfo resolveInfo : resolveInfoList) { + if (resolveInfo.serviceInfo == null) continue; + + if (resolveInfo.serviceInfo.packageName == null + || resolveInfo.serviceInfo.name == null) { + //Really? + continue; + } + + if (!resolveInfo.serviceInfo.permission.equals( + cyanogenmod.platform.Manifest.permission.BIND_WEATHER_PROVIDER_SERVICE)) { + continue; + } + WeatherProviderServiceInfo serviceInfo = new WeatherProviderServiceInfo(); + serviceInfo.componentName = new ComponentName(resolveInfo.serviceInfo.packageName, + resolveInfo.serviceInfo.name); + serviceInfo.isActive = serviceInfo.componentName.equals(activeService); + serviceInfo.caption = resolveInfo.loadLabel(pm); + serviceInfo.icon = resolveInfo.loadIcon(pm); + serviceInfo.settingsComponentName = getSettingsComponent(pm, resolveInfo); + + weatherProviderServiceInfos.add(serviceInfo); + } + + final PreferenceScreen ps = getPreferenceScreen(); + if (!weatherProviderServiceInfos.isEmpty()) { + if (ps.findPreference(PREFERENCE_GENERAL) == null) { + ps.addPreference(mGeneralSettingsCategory); + } + if (ps.findPreference(PREFERENCE_PROVIDERS) == null) { + ps.addPreference(mProvidersCategory); + } + + mProvidersCategory.removeAll(); + for (WeatherProviderServiceInfo info : weatherProviderServiceInfos) { + mProvidersCategory.addPreference(new WeatherProviderPreference(mContext, info)); + } + + Preference addServicePreference = new Preference(mContext); + addServicePreference.setTitle(R.string.weather_settings_add_weather_provider); + addServicePreference.setIcon(R.drawable.ic_add); + addServicePreference.setOnPreferenceClickListener( + new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + launchGetWeatherProviders(); + return false; + } + }); + mProvidersCategory.addPreference(addServicePreference); + + } else { + ps.removePreference(mGeneralSettingsCategory); + ps.removePreference(mProvidersCategory); + } + + } + + /** + * Gets the currently selected temperature unit. + * If none is selected yet, returns a unit appropriate for the current locale + */ + public static int getSelectedTemperatureUnit(Context context) { + int tempUnit = CMSettings.Global.getInt(context.getContentResolver(), + CMSettings.Global.WEATHER_TEMPERATURE_UNIT, -1); + if (tempUnit != -1) { + return tempUnit; + } + + Locale locale = context.getResources().getConfiguration().locale; + boolean useFahrenheit = locale.equals(Locale.US) + || locale.toString().equals("ms_MY") // Malaysia + || locale.toString().equals("si_LK"); // Sri Lanka + return useFahrenheit + ? WeatherContract.WeatherColumns.TempUnit.FAHRENHEIT + : WeatherContract.WeatherColumns.TempUnit.CELSIUS; + } + + private static class WeatherProviderPreference extends Preference + implements View.OnClickListener { + private WeatherProviderServiceInfo mInfo; + private View mView; + private RadioButton mRadioButton; + private View mSettingsButton; + private Context mContext; + + public WeatherProviderPreference(Context context, WeatherProviderServiceInfo info) { + super(context); + mInfo = info; + mContext = context; + + setLayoutResource(R.layout.weather_service_provider_info_row); + setTitle(mInfo.caption); + setIcon(mInfo.icon); + } + + @Override + protected void onBindView(final View view) { + super.onBindView(view); + mView = view; + mView.setOnClickListener(this); + + mRadioButton = (RadioButton) view.findViewById(R.id.radio); + mRadioButton.setChecked(mInfo.isActive); + mRadioButton.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + view.onTouchEvent(event); + return false; + } + }); + + boolean showSettings = mInfo.settingsComponentName != null; + View settingsDivider = view.findViewById(R.id.divider); + settingsDivider.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); + + mSettingsButton = view.findViewById(R.id.settings); + mSettingsButton.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); + mSettingsButton.setAlpha(mInfo.isActive ? 1f : Utils.DISABLED_ALPHA); + mSettingsButton.setEnabled(mInfo.isActive); + mSettingsButton.setFocusable(mInfo.isActive); + mSettingsButton.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + if (v == mView) { + v.setPressed(true); + setActiveWeatherProviderService(); + } + launchSettingsActivity(mInfo); + } + + private boolean isActiveProvider() { + return mInfo.isActive; + } + + public void setActiveState(boolean active) { + mInfo.isActive = active; + mRadioButton.setChecked(active); + + boolean hasSettings = mInfo.settingsComponentName != null; + if (hasSettings) { + mSettingsButton.setAlpha(mInfo.isActive ? 1f : Utils.DISABLED_ALPHA); + mSettingsButton.setEnabled(mInfo.isActive); + mSettingsButton.setFocusable(mInfo.isActive); + } + } + + private void launchSettingsActivity(WeatherProviderServiceInfo info) { + if (info != null && info.settingsComponentName != null) { + try { + mContext.startActivity(new Intent().setComponent(info.settingsComponentName)); + } catch (ActivityNotFoundException e) { + Toast.makeText(mContext, + R.string.weather_settings_activity_not_found, + Toast.LENGTH_LONG) + .show(); + Log.w(TAG, info.settingsComponentName + " not found"); + } + } + } + + private void setActiveWeatherProviderService() { + if (!mInfo.isActive) { + markAsActiveProvider(); + CMSettings.Secure.putString(mContext.getContentResolver(), + CMSettings.Secure.WEATHER_PROVIDER_SERVICE, + mInfo.componentName.flattenToString()); + } + } + + private void markAsActiveProvider() { + // Check for current active provider + PreferenceCategory providersCategory = (PreferenceCategory) findPreferenceInHierarchy( + WeatherServiceSettings.PREFERENCE_PROVIDERS); + if (providersCategory != null) { + final int count = providersCategory.getPreferenceCount(); + for (int index = 0; index < count; index++) { + Preference p = providersCategory.getPreference(index); + if (p instanceof WeatherProviderPreference) { + WeatherProviderPreference preference = (WeatherProviderPreference) p; + if (preference.isActiveProvider()) { + preference.setActiveState(false); + break; + } + } + } + } + // Mark this provider as active + setActiveState(true); + } + } + + private ComponentName getSettingsComponent(PackageManager pm, ResolveInfo resolveInfo) { + if (resolveInfo == null + || resolveInfo.serviceInfo == null + || resolveInfo.serviceInfo.metaData == null) { + return null; + } + String cn = null; + XmlResourceParser parser = null; + Exception caughtException = null; + + try { + parser = resolveInfo.serviceInfo.loadXmlMetaData(pm, + WeatherProviderService.SERVICE_META_DATA); + if (parser == null) { + Log.w(TAG, "Can't find " + WeatherProviderService.SERVICE_META_DATA + " meta-data"); + return null; + } + Resources res = + pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo); + AttributeSet attrs = Xml.asAttributeSet(parser); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && type != XmlPullParser.START_TAG) { + } + String nodeName = parser.getName(); + if (!"weather-provider-service".equals(nodeName)) { + Log.w(TAG, "Meta-data does not start with weather-provider-service tag"); + return null; + } + //Will use Dream styleable for now, it has the attribute we need + TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.Dream); + cn = sa.getString(com.android.internal.R.styleable.Dream_settingsActivity); + sa.recycle(); + } catch (PackageManager.NameNotFoundException e) { + caughtException = e; + } catch (IOException e) { + caughtException = e; + } catch (XmlPullParserException e) { + caughtException = e; + } finally { + if (parser != null) parser.close(); + } + if (caughtException != null) { + Log.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, + caughtException); + return null; + } + if (cn != null && cn.indexOf('/') < 0) { + cn = resolveInfo.serviceInfo.packageName + "/" + cn; + } + return cn == null ? null : ComponentName.unflattenFromString(cn); + } + + private ComponentName getEnabledWeatherServiceProvider() { + String activeWeatherServiceProvider = CMSettings.Secure.getString( + mContext.getContentResolver(), CMSettings.Secure.WEATHER_PROVIDER_SERVICE); + if (activeWeatherServiceProvider == null) return null; + return ComponentName.unflattenFromString(activeWeatherServiceProvider); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + ViewGroup contentRoot = (ViewGroup) getListView().getParent(); + View emptyView = getActivity().getLayoutInflater().inflate( + R.layout.empty_weather_state, contentRoot, false); + TextView emptyTextView = (TextView) emptyView.findViewById(R.id.message); + emptyTextView.setText(R.string.weather_settings_no_services_prompt); + + Button addProviderButton = (Button) emptyView.findViewById(R.id.add_weather_provider); + addProviderButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + launchGetWeatherProviders(); + } + }); + + contentRoot.addView(emptyView); + + ListView listView = getListView(); + listView.setEmptyView(emptyView); + } + + private class WeatherProviderServiceInfo { + CharSequence caption; + Drawable icon; + boolean isActive; + ComponentName componentName; + public ComponentName settingsComponentName; + } +} diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java index e01a843..ebd32c1 100644 --- a/src/com/android/settings/dashboard/DashboardSummary.java +++ b/src/com/android/settings/dashboard/DashboardSummary.java @@ -43,6 +43,7 @@ import com.android.settings.HelpUtils; import com.android.settings.InstrumentedFragment; import com.android.settings.R; import com.android.settings.SettingsActivity; +import com.android.settings.Utils; import com.android.settings.widget.SwitchBar; import java.util.List; @@ -105,6 +106,10 @@ public class DashboardSummary extends InstrumentedFragment { filter.addAction(Intent.ACTION_PACKAGE_REPLACED); filter.addDataScheme("package"); getActivity().registerReceiver(mHomePackageReceiver, filter); + + final IntentFilter airplaneModeFilter + = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); + getActivity().registerReceiver(mHomePackageReceiver, airplaneModeFilter); } @Override @@ -165,6 +170,9 @@ public class DashboardSummary extends InstrumentedFragment { tileView.setTile(tile); + if (tile.id == R.id.mobile_networks) { + tileView.setEnabledTile(!Utils.isAirplaneModeEnabled(context)); + } categoryContent.addView(tileView); } diff --git a/src/com/android/settings/dashboard/DashboardTileView.java b/src/com/android/settings/dashboard/DashboardTileView.java index 6790136..50bfabe 100644 --- a/src/com/android/settings/dashboard/DashboardTileView.java +++ b/src/com/android/settings/dashboard/DashboardTileView.java @@ -150,5 +150,13 @@ public class DashboardTileView extends FrameLayout implements View.OnClickListen return mSwitch; } - + public void setEnabledTile(boolean enabled) { + mImageView.setAlpha(enabled ? 1f : Utils.DISABLED_ALPHA); + mTitleTextView.setEnabled(enabled); + mStatusTextView.setEnabled(enabled); + mSwitch.setEnabled(enabled); + mSwitch.setClickable(enabled); + setFocusable(enabled); + setEnabled(enabled); + } } diff --git a/src/com/android/settings/dashboard/SearchResultsSummary.java b/src/com/android/settings/dashboard/SearchResultsSummary.java index ca764b3..9b1b169 100644 --- a/src/com/android/settings/dashboard/SearchResultsSummary.java +++ b/src/com/android/settings/dashboard/SearchResultsSummary.java @@ -236,7 +236,9 @@ public class SearchResultsSummary extends InstrumentedFragment { mShowResults = true; mQuery = cursor.getString(0); - mSearchView.setQuery(mQuery, false); + if (mSearchView != null) { + mSearchView.setQuery(mQuery, false); + } } }); mSuggestionsListView.addHeaderView( diff --git a/src/com/android/settings/deviceinfo/SimStatus.java b/src/com/android/settings/deviceinfo/SimStatus.java index 036d00f..b40a255 100644 --- a/src/com/android/settings/deviceinfo/SimStatus.java +++ b/src/com/android/settings/deviceinfo/SimStatus.java @@ -44,6 +44,7 @@ import android.widget.ListView; import com.android.internal.logging.MetricsLogger; import com.android.internal.telephony.DefaultPhoneNotifier; import com.android.internal.telephony.Phone; +import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneFactory; import com.android.settings.InstrumentedPreferenceActivity; import com.android.settings.R; @@ -170,6 +171,8 @@ public class SimStatus extends InstrumentedPreferenceActivity { CB_AREA_INFO_SENDER_PERMISSION, null); // Ask CellBroadcastReceiver to broadcast the latest area info received Intent getLatestIntent = new Intent(GET_LATEST_CB_AREA_INFO_ACTION); + getLatestIntent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, + mSir.getSubscriptionId()); sendBroadcastAsUser(getLatestIntent, UserHandle.ALL, CB_AREA_INFO_SENDER_PERMISSION); } @@ -294,7 +297,8 @@ public class SimStatus extends InstrumentedPreferenceActivity { String dataDisplay = Utils.getServiceStateString(dataState, mRes); - setSummaryText(KEY_SERVICE_STATE, "Voice: " + voiceDisplay + " / Data: " + dataDisplay); + setSummaryText(KEY_SERVICE_STATE, getString(R.string.sim_status_format_string, + voiceDisplay, dataDisplay)); if (serviceState.getRoaming()) { setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_in)); @@ -373,6 +377,12 @@ public class SimStatus extends InstrumentedPreferenceActivity { } mPhone = phone; + updateAreaInfo(""); + Intent getLatestIntent = new Intent(GET_LATEST_CB_AREA_INFO_ACTION); + getLatestIntent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, + mSir.getSubscriptionId()); + sendBroadcastAsUser(getLatestIntent, UserHandle.ALL, + CB_AREA_INFO_SENDER_PERMISSION); mPhoneStateListener = new PhoneStateListener(mSir.getSubscriptionId()) { @Override public void onDataConnectionStateChanged(int state) { diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java index 63d9335..df3646e 100644 --- a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java +++ b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java @@ -19,6 +19,8 @@ package com.android.settings.fingerprint; import android.content.Intent; import android.hardware.fingerprint.FingerprintManager; import android.os.Bundle; +import android.view.View; +import android.widget.TextView; import com.android.internal.logging.MetricsLogger; import com.android.settings.ChooseLockSettingsHelper; @@ -31,6 +33,10 @@ public class FingerprintEnrollFindSensor extends FingerprintEnrollBase { private static final int CONFIRM_REQUEST = 1; private static final int ENROLLING = 2; + private static final int SENSOR_LOCATION_BACK = 0; + private static final int SENSOR_LOCATION_FRONT = 1; + private static final int SENSOR_LOCATION_LEFT = 2; + private static final int SENSOR_LOCATION_RIGHT = 3; public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock"; private FingerprintLocationAnimationView mAnimation; @@ -48,6 +54,21 @@ public class FingerprintEnrollFindSensor extends FingerprintEnrollBase { } mAnimation = (FingerprintLocationAnimationView) findViewById( R.id.fingerprint_sensor_location_animation); + + int sensorLocation = getResources().getInteger(R.integer.config_fingerprintSensorLocation); + if (sensorLocation < SENSOR_LOCATION_BACK || sensorLocation > SENSOR_LOCATION_RIGHT) { + sensorLocation = SENSOR_LOCATION_BACK; + } + final String location = getResources().getStringArray( + R.array.security_settings_fingerprint_sensor_locations)[sensorLocation]; + TextView message = (TextView) findViewById(R.id.find_sensor_message); + message.setText(getString( + R.string.security_settings_fingerprint_enroll_find_sensor_message_cm, + location)); + if (sensorLocation != SENSOR_LOCATION_BACK) { + findViewById(R.id.fingerprint_sensor_location_front_overlay) + .setVisibility(View.VISIBLE); + } } @Override diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java index 5753459..2e66d16 100644 --- a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java +++ b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.os.Bundle; import android.os.UserHandle; import android.text.TextUtils; +import android.provider.Settings.Global; import android.view.View; import com.android.internal.logging.MetricsLogger; @@ -43,11 +44,10 @@ public class FingerprintEnrollIntroduction extends FingerprintEnrollBase { findViewById(R.id.cancel_button).setOnClickListener(this); final View learnMoreButton = findViewById(R.id.learn_more_button); - // If help url is not overlaid, remove the button. - if (TextUtils.isEmpty(getString(R.string.help_url_fingerprint))) { + learnMoreButton.setOnClickListener(this); + if (TextUtils.isEmpty(getString(R.string.help_url_fingerprint)) || + Global.getInt(getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) { learnMoreButton.setVisibility(View.GONE); - } else { - learnMoreButton.setOnClickListener(this); } final int passwordQuality = new ChooseLockSettingsHelper(this).utils() @@ -100,7 +100,9 @@ public class FingerprintEnrollIntroduction extends FingerprintEnrollBase { private void launchFingerprintHelp() { Intent helpIntent = HelpUtils.getHelpIntent(this, getString(R.string.help_url_fingerprint), getClass().getName()); - startActivity(helpIntent); + if (helpIntent != null) { + startActivity(helpIntent); + } } @Override diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java index 269249a..5a6bd1b 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageBase.java +++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java @@ -46,6 +46,7 @@ public abstract class PowerUsageBase extends SettingsPreferenceFragment { private String mBatteryLevel; private String mBatteryStatus; + private boolean mHideRefresh = false; @Override public void onAttach(Activity activity) { @@ -102,11 +103,13 @@ public abstract class PowerUsageBase extends SettingsPreferenceFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); - MenuItem refresh = menu.add(0, MENU_STATS_REFRESH, 0, R.string.menu_stats_refresh) - .setIcon(com.android.internal.R.drawable.ic_menu_refresh) - .setAlphabeticShortcut('r'); - refresh.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | - MenuItem.SHOW_AS_ACTION_WITH_TEXT); + if (!mHideRefresh) { + MenuItem refresh = menu.add(0, MENU_STATS_REFRESH, 0, R.string.menu_stats_refresh) + .setIcon(com.android.internal.R.drawable.ic_menu_refresh) + .setAlphabeticShortcut('r'); + refresh.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | + MenuItem.SHOW_AS_ACTION_WITH_TEXT); + } } public boolean onOptionsItemSelected(MenuItem item) { @@ -142,6 +145,10 @@ public abstract class PowerUsageBase extends SettingsPreferenceFragment { return false; } + void hideRefreshButton(boolean hide) { + mHideRefresh = hide; + } + static final int MSG_REFRESH_STATS = 100; private final Handler mHandler = new Handler() { diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java index 910daa7..135b70e 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java +++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java @@ -29,6 +29,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; +import android.graphics.PorterDuff; import android.net.Uri; import android.os.BatteryStats; import android.os.Bundle; @@ -353,6 +354,7 @@ public class PowerUsageDetail extends PowerUsageBase implements Button.OnClickLi mControlsParent = (PreferenceCategory) findPreference(KEY_CONTROLS_PARENT); mMessagesParent = (PreferenceCategory) findPreference(KEY_MESSAGES_PARENT); mPackagesParent = (PreferenceCategory) findPreference(KEY_PACKAGES_PARENT); + hideRefreshButton(true); createDetails(); } @@ -478,7 +480,9 @@ public class PowerUsageDetail extends PowerUsageBase implements Button.OnClickLi if (appIcon == null) { appIcon = getActivity().getPackageManager().getDefaultActivityIcon(); } - + if (appIcon != null) { + appIcon.setTintMode(PorterDuff.Mode.SRC_ATOP); + } if (pkg == null && mPackages != null) { pkg = mPackages[0]; } diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 8f8a5a4..fda2a7e 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -285,10 +285,8 @@ public class PowerUsageSummary extends PowerUsageBase case MENU_BATTERY_SAVER: Resources res = getResources(); - final int defWarnLevel = res.getInteger( - com.android.internal.R.integer.config_lowBatteryWarningLevel); final int value = Settings.Global.getInt(getContentResolver(), - Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel); + Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0); int selectedIndex = -1; final int[] intVals = res.getIntArray(R.array.battery_saver_trigger_values); diff --git a/src/com/android/settings/hardware/VibratorIntensity.java b/src/com/android/settings/hardware/VibratorIntensity.java index e847933..a778f36 100644 --- a/src/com/android/settings/hardware/VibratorIntensity.java +++ b/src/com/android/settings/hardware/VibratorIntensity.java @@ -42,7 +42,7 @@ import cyanogenmod.providers.CMSettings; import com.android.settings.R; public class VibratorIntensity extends DialogPreference implements - SeekBar.OnSeekBarChangeListener { + SeekBar.OnSeekBarChangeListener, PreferenceManager.OnActivityStopListener { private static final String PREF_NAME = "vibrator_intensity"; private SeekBar mSeekBar; private TextView mValue; @@ -120,7 +120,10 @@ public class VibratorIntensity extends DialogPreference implements getContext().getResources().getColor(android.R.color.holo_red_light)); mSeekBar.setOnSeekBarChangeListener(this); - mSeekBar.setProgress(intensityToPercent(mMinValue, mMaxValue, mOriginalValue)); + mSeekBar.setMax(mMaxValue - mMinValue); + mSeekBar.setProgress(mOriginalValue - mMinValue); + + getPreferenceManager().registerOnActivityStopListener(this); } @Override @@ -134,7 +137,7 @@ public class VibratorIntensity extends DialogPreference implements defaultsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mSeekBar.setProgress(intensityToPercent(mMinValue, mMaxValue, mDefaultValue)); + mSeekBar.setProgress(mDefaultValue - mMinValue); } }); } @@ -146,11 +149,22 @@ public class VibratorIntensity extends DialogPreference implements if (positiveResult) { // Store percent value in SharedPreferences object SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); - prefs.edit().putInt(PREF_NAME, mSeekBar.getProgress()).commit(); + int intensity = mSeekBar.getProgress() + mMinValue; + int percent = intensityToPercent(mMinValue, mMaxValue, intensity); + prefs.edit().putInt(PREF_NAME, percent).commit(); + CMSettings.Secure.putInt(getContext().getContentResolver(), + CMSettings.Secure.VIBRATOR_INTENSITY, intensity); } else { CMSettings.Secure.putInt(getContext().getContentResolver(), CMSettings.Secure.VIBRATOR_INTENSITY, mOriginalValue); } + + getPreferenceManager().unregisterOnActivityStopListener(this); + } + + @Override + public void onActivityStop() { + mHardware.setVibratorIntensity(mOriginalValue); } public static void restore(Context context) { @@ -161,20 +175,17 @@ public class VibratorIntensity extends DialogPreference implements SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); int min = hardware.getVibratorMinIntensity(); int max = hardware.getVibratorMaxIntensity(); - int defaultValue = intensityToPercent(min, max, - hardware.getVibratorDefaultIntensity()); - int percent = prefs.getInt(PREF_NAME, defaultValue); + int defaultIntensity = hardware.getVibratorDefaultIntensity(); + int percent = prefs.getInt(PREF_NAME, intensityToPercent(min, max, defaultIntensity)); CMSettings.Secure.putInt(context.getContentResolver(), - CMSettings.Secure.VIBRATOR_INTENSITY, percentToIntensity(min, max, - percentToIntensity(min, max, percent))); + CMSettings.Secure.VIBRATOR_INTENSITY, percentToIntensity(min, max, percent)); } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - boolean shouldWarn = - mWarningValue > 0 && progress >= intensityToPercent(mMinValue, mMaxValue, - mWarningValue); + int intensity = progress + mMinValue; + boolean shouldWarn = mWarningValue > 0 && intensity >= mWarningValue; if (mProgressDrawable != null) { mProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null); @@ -183,10 +194,7 @@ public class VibratorIntensity extends DialogPreference implements mProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null); } - CMSettings.Secure.putInt(getContext().getContentResolver(), - CMSettings.Secure.VIBRATOR_INTENSITY, percentToIntensity(mMinValue, mMaxValue, - progress)); - mValue.setText(String.format("%d%%", progress)); + mValue.setText(String.format("%d%%", intensityToPercent(mMinValue, mMaxValue, intensity))); } @Override @@ -196,12 +204,13 @@ public class VibratorIntensity extends DialogPreference implements @Override public void onStopTrackingTouch(SeekBar seekBar) { + mHardware.setVibratorIntensity(seekBar.getProgress() + mMinValue); Vibrator vib = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); vib.vibrate(200); } - private static int intensityToPercent(double minValue, double maxValue, int value) { - double percent = (value - minValue) * (100 / (maxValue - minValue)); + private static int intensityToPercent(int minValue, int maxValue, int value) { + int percent = Math.round((value - minValue) * (100.f / (maxValue - minValue))); if (percent > 100) { percent = 100; @@ -209,11 +218,11 @@ public class VibratorIntensity extends DialogPreference implements percent = 0; } - return (int) percent; + return percent; } private static int percentToIntensity(int minValue, int maxValue, int percent) { - int value = Math.round((((maxValue - minValue) * percent) / 100) + minValue); + int value = Math.round((((maxValue - minValue) * percent) / 100.f) + minValue); if (value > maxValue) { value = maxValue; diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java index 1e7b35c..7c531da 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java +++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java @@ -93,7 +93,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings"; private static final String KEY_POINTER_SETTINGS_CATEGORY = "pointer_settings_category"; private static final String KEY_PREVIOUSLY_ENABLED_SUBTYPES = "previously_enabled_subtypes"; - private static final String KEY_HIGH_TOUCH_SENSITIVITY = "high_touch_sensitivity"; private static final String KEY_TOUCHSCREEN_HOVERING = "touchscreen_hovering"; private static final String KEY_TRACKPAD_SETTINGS = "gesture_pad_settings"; private static final String KEY_STYLUS_GESTURES = "stylus_gestures"; @@ -115,7 +114,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment private int mDefaultInputMethodSelectorVisibility = 0; private ListPreference mShowInputMethodSelectorPref; private SwitchPreference mStylusIconEnabled; - private SwitchPreference mHighTouchSensitivity; private SwitchPreference mTouchscreenHovering; private PreferenceCategory mKeyboardSettingsCategory; private PreferenceCategory mHardKeyboardCategory; @@ -203,7 +201,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment mStylusGestures = (PreferenceScreen) findPreference(KEY_STYLUS_GESTURES); mStylusIconEnabled = (SwitchPreference) findPreference(KEY_STYLUS_ICON_ENABLED); - mHighTouchSensitivity = (SwitchPreference) findPreference(KEY_HIGH_TOUCH_SENSITIVITY); mTouchscreenHovering = (SwitchPreference) findPreference(KEY_TOUCHSCREEN_HOVERING); @@ -213,15 +210,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment pointerSettingsCategory.removePreference(mStylusIconEnabled); } - if (!mHardware.isSupported( - CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { - pointerSettingsCategory.removePreference(mHighTouchSensitivity); - mHighTouchSensitivity = null; - } else { - mHighTouchSensitivity.setChecked( - mHardware.get(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)); - } - if (!mHardware.isSupported(CMHardwareManager.FEATURE_TOUCH_HOVERING)) { pointerSettingsCategory.removePreference(mTouchscreenHovering); mTouchscreenHovering = null; @@ -433,12 +421,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment if (preference == mStylusIconEnabled) { Settings.System.putInt(getActivity().getContentResolver(), Settings.System.STYLUS_ICON_ENABLED, mStylusIconEnabled.isChecked() ? 1 : 0); - } else if (preference == mHighTouchSensitivity) { - boolean mHighTouchSensitivityEnable = mHighTouchSensitivity.isChecked(); - CMSettings.System.putInt(getActivity().getContentResolver(), - CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE, - mHighTouchSensitivityEnable ? 1 : 0); - return true; } else if (preference == mTouchscreenHovering) { boolean touchHoveringEnable = mTouchscreenHovering.isChecked(); CMSettings.Secure.putInt(getActivity().getContentResolver(), @@ -785,13 +767,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment public static void restore(Context context) { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); final CMHardwareManager hardware = CMHardwareManager.getInstance(context); - if (hardware.isSupported(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { - final boolean enabled = prefs.getBoolean(KEY_HIGH_TOUCH_SENSITIVITY, - hardware.get(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)); - CMSettings.System.putInt(context.getContentResolver(), - CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE, - enabled ? 1 : 0); - } if (hardware.isSupported(CMHardwareManager.FEATURE_TOUCH_HOVERING)) { final boolean enabled = prefs.getBoolean(KEY_TOUCHSCREEN_HOVERING, hardware.get(CMHardwareManager.FEATURE_TOUCH_HOVERING)); diff --git a/src/com/android/settings/livedisplay/DisplayColor.java b/src/com/android/settings/livedisplay/DisplayColor.java index 5db508f..f6fee82 100644 --- a/src/com/android/settings/livedisplay/DisplayColor.java +++ b/src/com/android/settings/livedisplay/DisplayColor.java @@ -16,17 +16,13 @@ package com.android.settings.livedisplay; -import static cyanogenmod.hardware.CMHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION; - import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.os.UserHandle; import android.preference.DialogPreference; -import android.provider.Settings; import android.util.AttributeSet; import android.view.View; import android.widget.Button; @@ -36,8 +32,7 @@ import android.widget.TextView; import com.android.settings.IntervalSeekBar; import com.android.settings.R; -import cyanogenmod.hardware.CMHardwareManager; -import cyanogenmod.providers.CMSettings; +import cyanogenmod.hardware.LiveDisplayManager; /** * Special preference type that allows configuration of Color settings @@ -46,11 +41,7 @@ public class DisplayColor extends DialogPreference { private static final String TAG = "ColorCalibration"; private final Context mContext; - - private final int minRGB; - private final int maxRGB; - private final float defaultRGB; - private final boolean useCMHW; + private final LiveDisplayManager mLiveDisplay; // These arrays must all match in length and order private static final int[] SEEKBAR_ID = new int[] { @@ -74,19 +65,7 @@ public class DisplayColor extends DialogPreference { super(context, attrs); mContext = context; - - final CMHardwareManager mHardware = CMHardwareManager.getInstance(context); - useCMHW = mHardware.isSupported(FEATURE_DISPLAY_COLOR_CALIBRATION); - if (useCMHW) { - minRGB = mHardware.getDisplayColorCalibrationMin(); - maxRGB = mHardware.getDisplayColorCalibrationMax(); - defaultRGB = (float) mHardware.getDisplayColorCalibrationDefault() / maxRGB; - } else { - // Initialize these just to avoid compiler errors. - minRGB = 20; - maxRGB = 100; - defaultRGB = 1.0f; - } + mLiveDisplay = LiveDisplayManager.getInstance(mContext); setDialogLayoutResource(R.layout.display_color_calibration); } @@ -105,38 +84,16 @@ public class DisplayColor extends DialogPreference { protected void onBindDialogView(View view) { super.onBindDialogView(view); - String colorAdjustmentTemp = CMSettings.System.getStringForUser( - mContext.getContentResolver(), - CMSettings.System.DISPLAY_COLOR_ADJUSTMENT, - UserHandle.USER_CURRENT); - String[] colorAdjustment = colorAdjustmentTemp == null ? - null : colorAdjustmentTemp.split(" "); - if (colorAdjustment == null || colorAdjustment.length != 3) { - colorAdjustment = new String[] { Float.toString(defaultRGB), - Float.toString(defaultRGB), Float.toString(defaultRGB) }; - } - try { - mOriginalColors[0] = Float.parseFloat(colorAdjustment[0]); - mOriginalColors[1] = Float.parseFloat(colorAdjustment[1]); - mOriginalColors[2] = Float.parseFloat(colorAdjustment[2]); - } catch (NumberFormatException e) { - mOriginalColors[0] = defaultRGB; - mOriginalColors[1] = defaultRGB; - mOriginalColors[2] = defaultRGB; - } - + System.arraycopy(mLiveDisplay.getColorAdjustment(), 0, mOriginalColors, 0, 3); System.arraycopy(mOriginalColors, 0, mCurrentColors, 0, 3); for (int i = 0; i < SEEKBAR_ID.length; i++) { IntervalSeekBar seekBar = (IntervalSeekBar) view.findViewById(SEEKBAR_ID[i]); TextView value = (TextView) view.findViewById(SEEKBAR_VALUE_ID[i]); mSeekBars[i] = new ColorSeekBar(seekBar, value, i); - if (useCMHW) { - mSeekBars[i].mSeekBar.setMinimum((float) minRGB / maxRGB); - /* Maximum hasn't changed but it's relative to the minimum so it needs - to be reset */ - mSeekBars[i].mSeekBar.setMaximum(1.0f); - } + mSeekBars[i].mSeekBar.setMinimum(0.1f); + mSeekBars[i].mSeekBar.setMaximum(1.0f); + mSeekBars[i].mSeekBar.setProgressFloat(mCurrentColors[i]); int percent = Math.round(100F * mCurrentColors[i]); value.setText(String.format("%d%%", percent)); @@ -155,8 +112,8 @@ public class DisplayColor extends DialogPreference { @Override public void onClick(View v) { for (int i = 0; i < mSeekBars.length; i++) { - mSeekBars[i].mSeekBar.setProgressFloat(defaultRGB); - mCurrentColors[i] = defaultRGB; + mSeekBars[i].mSeekBar.setProgressFloat(1.0f); + mCurrentColors[i] = 1.0f; } updateColors(mCurrentColors); } @@ -241,12 +198,7 @@ public class DisplayColor extends DialogPreference { } private void updateColors(float[] colors) { - CMSettings.System.putStringForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_COLOR_ADJUSTMENT, - new StringBuilder().append(colors[0]).append(" ") - .append(colors[1]).append(" ") - .append(colors[2]).toString(), - UserHandle.USER_CURRENT); + mLiveDisplay.setColorAdjustment(colors); } private class ColorSeekBar implements SeekBar.OnSeekBarChangeListener { diff --git a/src/com/android/settings/livedisplay/DisplayGamma.java b/src/com/android/settings/livedisplay/DisplayGamma.java deleted file mode 100644 index 2b44cea..0000000 --- a/src/com/android/settings/livedisplay/DisplayGamma.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (C) 2013-2015 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.livedisplay; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.content.res.Resources; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import android.preference.DialogPreference; -import android.preference.PreferenceManager; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.SeekBar; -import android.widget.TextView; - -import com.android.settings.R; - -import cyanogenmod.hardware.CMHardwareManager; -import cyanogenmod.providers.CMSettings; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Special preference type that allows configuration of Gamma settings - */ -public class DisplayGamma extends DialogPreference { - private static final String TAG = "GammaCalibration"; - - private static final int[] BAR_COLORS = new int[] { - R.string.color_red_title, - R.string.color_green_title, - R.string.color_blue_title - }; - - private GammaSeekBar[][] mSeekBars; - - private int[][] mCurrentColors; - private int[][] mOriginalColors; - private int mNumberOfControls; - private CMHardwareManager mHardware; - - public DisplayGamma(Context context, AttributeSet attrs) { - super(context, attrs); - - mHardware = CMHardwareManager.getInstance(context); - if (!mHardware.isSupported(CMHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION)) { - return; - } - - mNumberOfControls = mHardware.getNumGammaControls(); - mSeekBars = new GammaSeekBar[mNumberOfControls][BAR_COLORS.length]; - - mOriginalColors = new int[mNumberOfControls][]; - mCurrentColors = new int[mNumberOfControls][]; - - setDialogLayoutResource(R.layout.display_gamma_calibration); - } - - @Override - protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { - builder.setNeutralButton(R.string.settings_reset_button, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - } - }); - } - - @Override - protected void onBindDialogView(View view) { - super.onBindDialogView(view); - - final ViewGroup container = (ViewGroup) view.findViewById(R.id.gamma_container); - final LayoutInflater inflater = LayoutInflater.from(getContext()); - final SharedPreferences prefs = getSharedPreferences(); - final Resources res = container.getResources(); - final String[] gammaDescriptors = res.getStringArray(R.array.gamma_descriptors); - - // Create multiple sets of seekbars, depending on the - // number of controls the device has - for (int index = 0; index < mNumberOfControls; index++) { - mOriginalColors[index] = mHardware.getDisplayGammaCalibration(index); - mCurrentColors[index] = Arrays.copyOf(mOriginalColors[index], - mOriginalColors[index].length); - - final String defaultKey = "display_gamma_default_" + index; - if (!prefs.contains(defaultKey)) { - prefs.edit() - .putString(defaultKey, buildPreferenceValue(mOriginalColors[index])) - .apply(); - } - - if (mNumberOfControls != 1) { - TextView header = (TextView) inflater.inflate( - R.layout.display_gamma_calibration_header, container, false); - - if (index < gammaDescriptors.length) { - header.setText(gammaDescriptors[index]); - } else { - header.setText(res.getString( - R.string.gamma_tuning_control_set_header, index + 1)); - } - container.addView(header); - } - - int min = mHardware.getDisplayGammaCalibrationMin(); - int max = mHardware.getDisplayGammaCalibrationMax(); - for (int color = 0; color < BAR_COLORS.length; color++) { - ViewGroup item = (ViewGroup) inflater.inflate( - R.layout.display_gamma_calibration_item, container, false); - - mSeekBars[index][color] = new GammaSeekBar(index, color, item, min, max); - mSeekBars[index][color].setGamma(mCurrentColors[index][color]); - // make sure to add the seekbar group to the container _after_ - // creating GammaSeekBar, so that GammaSeekBar has a chance to - // get the correct subviews without getting confused by duplicate IDs - container.addView(item); - } - } - } - - @Override - protected void showDialog(Bundle state) { - super.showDialog(state); - - // can't use onPrepareDialogBuilder for this as we want the dialog - // to be kept open on click - AlertDialog d = (AlertDialog) getDialog(); - Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL); - defaultsButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - for (int index = 0; index < mSeekBars.length; index++) { - final SharedPreferences prefs = getSharedPreferences(); - final String defaultKey = "display_gamma_default_" + index; - // this key is guaranteed to be present, as we have - // created it in onBindDialogView() - final String value = prefs.getString(defaultKey, null); - final String[] defaultColors = value.split(" "); - - for (int color = 0; color < BAR_COLORS.length; color++) { - int val = Integer.valueOf(defaultColors[color]); - mSeekBars[index][color].setGamma(val); - mCurrentColors[index][color] = val; - } - writeDisplayGamma(getContext(), index, mCurrentColors[index]); - } - } - }); - } - - @Override - protected void onDialogClosed(boolean positiveResult) { - super.onDialogClosed(positiveResult); - - if (positiveResult) { - Editor editor = getEditor(); - for (int i = 0; i < mNumberOfControls; i++) { - editor.putString("display_gamma_" + i, - buildPreferenceValue(mHardware.getDisplayGammaCalibration(i))); - } - editor.apply(); - } else if (mOriginalColors != null) { - for (int i = 0; i < mNumberOfControls; i++) { - writeDisplayGamma(getContext(), i, mOriginalColors[i]); - } - } - } - - @Override - protected Parcelable onSaveInstanceState() { - final Parcelable superState = super.onSaveInstanceState(); - if (getDialog() == null || !getDialog().isShowing()) { - return superState; - } - - // Save the dialog state - final SavedState myState = new SavedState(superState); - myState.controlCount = mNumberOfControls; - myState.currentColors = mCurrentColors; - myState.originalColors = mOriginalColors; - - // Restore the old state when the activity or dialog is being paused - for (int i = 0; i < mNumberOfControls; i++) { - writeDisplayGamma(getContext(), i, mOriginalColors[i]); - } - mOriginalColors = null; - - return myState; - } - - @Override - protected void onRestoreInstanceState(Parcelable state) { - if (state == null || !state.getClass().equals(SavedState.class)) { - // Didn't save state for us in onSaveInstanceState - super.onRestoreInstanceState(state); - return; - } - - SavedState myState = (SavedState) state; - super.onRestoreInstanceState(myState.getSuperState()); - mNumberOfControls = myState.controlCount; - mOriginalColors = myState.originalColors; - mCurrentColors = myState.currentColors; - - for (int index = 0; index < mNumberOfControls; index++) { - for (int color = 0; color < BAR_COLORS.length; color++) { - mSeekBars[index][color].setGamma(mCurrentColors[index][color]); - } - writeDisplayGamma(getContext(), index, mCurrentColors[index]); - } - } - - private String buildPreferenceValue(int[] colorValues) { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < colorValues.length; i++) { - if (i != 0) { - builder.append(" "); - } - builder.append(colorValues[i]); - } - return builder.toString(); - } - - public static void restore(Context context) { - final CMHardwareManager hardware = CMHardwareManager.getInstance(context); - if (!hardware.isSupported(CMHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION)) { - return; - } - - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - int[] rgb = new int[3]; - for (int i = 0; i < hardware.getNumGammaControls(); i++) { - final String value = prefs.getString("display_gamma_" + i, null); - if (value != null) { - final String[] values = value.split(" "); - rgb[0] = Integer.valueOf(values[0]); - rgb[1] = Integer.valueOf(values[1]); - rgb[2] = Integer.valueOf(values[2]); - writeDisplayGamma(context, i, rgb); - } - } - } - - private static class SavedState extends BaseSavedState { - int controlCount; - int[][] originalColors; - int[][] currentColors; - - public SavedState(Parcelable superState) { - super(superState); - } - - public SavedState(Parcel source) { - super(source); - controlCount = source.readInt(); - originalColors = new int[controlCount][]; - currentColors = new int[controlCount][]; - for (int i = 0; i < controlCount; i++) { - originalColors[i] = source.createIntArray(); - } - for (int i = 0; i < controlCount; i++) { - currentColors[i] = source.createIntArray(); - } - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeInt(controlCount); - for (int i = 0; i < controlCount; i++) { - dest.writeIntArray(originalColors[i]); - } - for (int i = 0; i < controlCount; i++) { - dest.writeIntArray(currentColors[i]); - } - } - - public static final Parcelable.Creator<SavedState> CREATOR = - new Parcelable.Creator<SavedState>() { - - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } - - private static void writeDisplayGamma(Context context, int index, int[] entries) { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < entries.length; i++) { - builder.append(i); - if (i != entries.length - 1) { - builder.append("|"); - } - } - CMSettings.Secure.putString(context.getContentResolver(), - CMSettings.Secure.DISPLAY_GAMMA_CALIBRATION_PREFIX + index, - builder.toString()); - } - - private class GammaSeekBar implements SeekBar.OnSeekBarChangeListener { - private int mControlIndex; - private int mColorIndex; - private int mOriginal; - private int mMin; - private int mMax; - private SeekBar mSeekBar; - private TextView mValue; - - public GammaSeekBar(int controlIndex, int colorIndex, ViewGroup container, - int min, int max) { - mControlIndex = controlIndex; - mColorIndex = colorIndex; - - mMin = min; - mMax = max; - - mValue = (TextView) container.findViewById(R.id.color_value); - mSeekBar = (SeekBar) container.findViewById(R.id.color_seekbar); - - TextView label = (TextView) container.findViewById(R.id.color_text); - label.setText(container.getContext().getString(BAR_COLORS[colorIndex])); - - mSeekBar.setMax(mMax - mMin); - mSeekBar.setProgress(0); - mValue.setText(String.valueOf(mSeekBar.getProgress() + mMin)); - - // this must be done last, we don't want to apply our initial value to the hardware - mSeekBar.setOnSeekBarChangeListener(this); - } - - public void setGamma(int gamma) { - mSeekBar.setProgress(gamma - mMin); - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { - mCurrentColors[mControlIndex][mColorIndex] = progress + mMin; - writeDisplayGamma(getContext(), mControlIndex, mCurrentColors[mControlIndex]); - } - mValue.setText(String.valueOf(progress + mMin)); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // Do nothing - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // Do nothing - } - } -} diff --git a/src/com/android/settings/livedisplay/DisplayTemperature.java b/src/com/android/settings/livedisplay/DisplayTemperature.java index 24ca747..350ef62 100644 --- a/src/com/android/settings/livedisplay/DisplayTemperature.java +++ b/src/com/android/settings/livedisplay/DisplayTemperature.java @@ -22,17 +22,20 @@ import android.content.DialogInterface; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.os.UserHandle; import android.preference.DialogPreference; -import android.provider.Settings; import android.util.AttributeSet; +import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.SeekBar; import android.widget.TextView; import com.android.settings.R; -import cyanogenmod.providers.CMSettings; + +import org.cyanogenmod.internal.util.MathUtils; + +import cyanogenmod.hardware.LiveDisplayConfig; +import cyanogenmod.hardware.LiveDisplayManager; /** * Preference for selection of color temperature range for LiveDisplay @@ -48,17 +51,16 @@ public class DisplayTemperature extends DialogPreference { private int mOriginalDayTemperature; private int mOriginalNightTemperature; - private final int mDefaultDayTemperature; - private final int mDefaultNightTemperature; + private final LiveDisplayManager mLiveDisplay; + private final LiveDisplayConfig mConfig; + + private static final int STEP = 100; public DisplayTemperature(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; - - mDefaultDayTemperature = mContext.getResources().getInteger( - org.cyanogenmod.platform.internal.R.integer.config_dayColorTemperature); - mDefaultNightTemperature = mContext.getResources().getInteger( - org.cyanogenmod.platform.internal.R.integer.config_nightColorTemperature); + mLiveDisplay = LiveDisplayManager.getInstance(mContext); + mConfig = mLiveDisplay.getConfig(); setDialogLayoutResource(R.layout.display_temperature); } @@ -77,14 +79,8 @@ public class DisplayTemperature extends DialogPreference { protected void onBindDialogView(View view) { super.onBindDialogView(view); - mOriginalDayTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_DAY, - mDefaultDayTemperature, - UserHandle.USER_CURRENT); - mOriginalNightTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_NIGHT, - mDefaultNightTemperature, - UserHandle.USER_CURRENT); + mOriginalDayTemperature = mLiveDisplay.getDayColorTemperature(); + mOriginalNightTemperature = mLiveDisplay.getNightColorTemperature(); SeekBar day = (SeekBar) view.findViewById(R.id.day_temperature_seekbar); TextView dayText = (TextView) view.findViewById(R.id.day_temperature_value); @@ -94,8 +90,8 @@ public class DisplayTemperature extends DialogPreference { TextView nightText = (TextView) view.findViewById(R.id.night_temperature_value); mNightTemperature = new ColorTemperatureSeekBar(night, nightText); - mDayTemperature.setProgress(mOriginalDayTemperature); - mNightTemperature.setProgress(mOriginalNightTemperature); + mDayTemperature.setTemperature(mOriginalDayTemperature); + mNightTemperature.setTemperature(mOriginalNightTemperature); } @Override @@ -109,8 +105,8 @@ public class DisplayTemperature extends DialogPreference { defaultsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mDayTemperature.setProgress(mDefaultDayTemperature); - mNightTemperature.setProgress(mDefaultNightTemperature); + mDayTemperature.setTemperature(mConfig.getDefaultDayTemperature()); + mNightTemperature.setTemperature(mConfig.getDefaultNightTemperature()); updateTemperature(true); } }); @@ -133,8 +129,8 @@ public class DisplayTemperature extends DialogPreference { final SavedState myState = new SavedState(superState); myState.originalDayTemperature = mOriginalDayTemperature; myState.originalNightTemperature = mOriginalNightTemperature; - myState.currentDayTemperature = mDayTemperature.getProgress(); - myState.currentNightTemperature = mNightTemperature.getProgress(); + myState.currentDayTemperature = mDayTemperature.getTemperature(); + myState.currentNightTemperature = mNightTemperature.getTemperature(); // Restore the old state when the activity or dialog is being paused updateTemperature(false); @@ -155,8 +151,8 @@ public class DisplayTemperature extends DialogPreference { mOriginalDayTemperature = myState.originalDayTemperature; mOriginalNightTemperature = myState.originalNightTemperature; - mDayTemperature.setProgress(myState.currentDayTemperature); - mNightTemperature.setProgress(myState.currentNightTemperature);; + mDayTemperature.setTemperature(myState.currentDayTemperature); + mNightTemperature.setTemperature(myState.currentNightTemperature);; updateTemperature(true); } @@ -202,33 +198,56 @@ public class DisplayTemperature extends DialogPreference { } private void updateTemperature(boolean accept) { - int day = accept ? mDayTemperature.getProgress() : mOriginalDayTemperature; - int night = accept ? mNightTemperature.getProgress() : mOriginalNightTemperature; + int day = accept ? mDayTemperature.getTemperature() : mOriginalDayTemperature; + int night = accept ? mNightTemperature.getTemperature() : mOriginalNightTemperature; callChangeListener(new Integer[] { day, night }); - CMSettings.System.putIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_DAY, day, - UserHandle.USER_CURRENT); + mLiveDisplay.setDayColorTemperature(day); + mLiveDisplay.setNightColorTemperature(night); + } - CMSettings.System.putIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_NIGHT, night, - UserHandle.USER_CURRENT); + int roundUp(int value) { + return ((value + STEP / 2) / STEP) * STEP; } private class ColorTemperatureSeekBar implements SeekBar.OnSeekBarChangeListener { private final SeekBar mSeekBar; private final TextView mValue; - private static final int MIN = 1000; - private static final int MAX = 10000; - private static final int STEP = 100; + private final int mMin; + private final int mMax; + + private final int mBalanceMin; + private final int mBalanceMax; + + private final int mBarMax; + + private final boolean mUseBalance; + private final double[] mBalanceCurve; public ColorTemperatureSeekBar(SeekBar seekBar, TextView value) { mSeekBar = seekBar; mValue = value; - - mSeekBar.setMax((MAX - MIN) / STEP); + mMin = mConfig.getColorTemperatureRange().getLower(); + mMax = mConfig.getColorTemperatureRange().getUpper(); + mBalanceMin = mConfig.getColorBalanceRange().getLower(); + mBalanceMax = mConfig.getColorBalanceRange().getUpper(); + mUseBalance = mConfig.hasFeature(LiveDisplayManager.FEATURE_COLOR_BALANCE) && + ((mBalanceMin != 0) || (mBalanceMax != 0)); + + if (mUseBalance) { + mBalanceCurve = MathUtils.powerCurve(mMin, mConfig.getDefaultDayTemperature(), mMax); + mBarMax = mBalanceMax - mBalanceMin; + } else { + mBalanceCurve = null; + mBarMax = (mMax - mMin) / STEP; + } + mSeekBar.setMax(mBarMax); mSeekBar.setOnSeekBarChangeListener(this); + + // init text value + int p = mSeekBar.getProgress(); + onProgressChanged(mSeekBar, p, false); } @Override @@ -236,17 +255,36 @@ public class DisplayTemperature extends DialogPreference { if (fromUser) { updateTemperature(true); } + + int displayValue; + if (mUseBalance) { + displayValue = roundUp(Math.round((float)MathUtils.linearToPowerCurve( + mBalanceCurve, (double)progress / (double)mBarMax))); + } else { + displayValue = progress * STEP + mMin; + } + Log.d(TAG, "onProgressChanged: progress=" + progress + " displayValue=" + displayValue); + mValue.setText(mContext.getResources().getString( - R.string.live_display_color_temperature_label, progress * STEP + MIN)); + R.string.live_display_color_temperature_label, displayValue)); } - public void setProgress(int progress) { - int p = Math.max(progress, MIN) - MIN; + public void setTemperature(int temperature) { + if (mUseBalance) { + double z = MathUtils.powerCurveToLinear(mBalanceCurve, (double)temperature); + mSeekBar.setProgress(Math.round((float)(z * (double)mBarMax))); + return; + } + int p = Math.max(temperature, mMin) - mMin; mSeekBar.setProgress(Math.round((float) p / STEP)); } - public int getProgress() { - return mSeekBar.getProgress() * STEP + MIN; + public int getTemperature() { + if (mUseBalance) { + return Math.round((float)MathUtils.linearToPowerCurve( + mBalanceCurve, (double)mSeekBar.getProgress() / (double)mBarMax)); + } + return mSeekBar.getProgress() * STEP + mMin; } @Override diff --git a/src/com/android/settings/livedisplay/LiveDisplay.java b/src/com/android/settings/livedisplay/LiveDisplay.java index 7000cc8..a3f4636 100644 --- a/src/com/android/settings/livedisplay/LiveDisplay.java +++ b/src/com/android/settings/livedisplay/LiveDisplay.java @@ -15,20 +15,19 @@ */ package com.android.settings.livedisplay; -import static cyanogenmod.hardware.CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT; -import static cyanogenmod.hardware.CMHardwareManager.FEATURE_COLOR_ENHANCEMENT; -import static cyanogenmod.hardware.CMHardwareManager.FEATURE_DISPLAY_MODES; -import static cyanogenmod.hardware.CMHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION; -import static cyanogenmod.hardware.CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT; +import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_CABC; +import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_COLOR_ADJUSTMENT; +import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_COLOR_ENHANCEMENT; +import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_DISPLAY_MODES; +import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_PICTURE_ADJUSTMENT; +import static cyanogenmod.hardware.LiveDisplayManager.MODE_OFF; +import static cyanogenmod.hardware.LiveDisplayManager.MODE_OUTDOOR; -import android.app.Activity; -import android.database.ContentObserver; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.database.ContentObserver; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; @@ -38,7 +37,6 @@ import android.preference.PreferenceCategory; import android.preference.PreferenceScreen; import android.preference.SwitchPreference; import android.provider.SearchIndexableResource; -import android.provider.Settings; import android.util.Log; import com.android.internal.util.ArrayUtils; @@ -48,14 +46,17 @@ import com.android.settings.Utils; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; -import cyanogenmod.hardware.CMHardwareManager; -import cyanogenmod.hardware.DisplayMode; -import cyanogenmod.providers.CMSettings; import org.cyanogenmod.internal.logging.CMMetricsLogger; import java.util.ArrayList; import java.util.List; +import cyanogenmod.hardware.CMHardwareManager; +import cyanogenmod.hardware.DisplayMode; +import cyanogenmod.hardware.LiveDisplayConfig; +import cyanogenmod.hardware.LiveDisplayManager; +import cyanogenmod.providers.CMSettings; + public class LiveDisplay extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener, Indexable { @@ -72,17 +73,10 @@ public class LiveDisplay extends SettingsPreferenceFragment implements private static final String KEY_LIVE_DISPLAY_TEMPERATURE = "live_display_color_temperature"; private static final String KEY_DISPLAY_COLOR = "color_calibration"; - private static final String KEY_DISPLAY_GAMMA = "gamma_tuning"; - private static final String KEY_SCREEN_COLOR_SETTINGS = "screencolor_settings"; + private static final String KEY_PICTURE_ADJUSTMENT = "picture_adjustment"; private static final String KEY_LIVE_DISPLAY_COLOR_PROFILE = "live_display_color_profile"; - public static final int MODE_OFF = 0; - public static final int MODE_NIGHT = 1; - public static final int MODE_AUTO = 2; - public static final int MODE_OUTDOOR = 3; - public static final int MODE_DAY = 4; - private final Handler mHandler = new Handler(); private final SettingsObserver mObserver = new SettingsObserver(); @@ -92,8 +86,9 @@ public class LiveDisplay extends SettingsPreferenceFragment implements private SwitchPreference mLowPower; private SwitchPreference mOutdoorMode; - private PreferenceScreen mScreenColorSettings; + private PictureAdjustment mPictureAdjustment; private DisplayTemperature mDisplayTemperature; + private DisplayColor mDisplayColor; private ListPreference mColorProfile; private String[] mColorProfileSummaries; @@ -102,26 +97,21 @@ public class LiveDisplay extends SettingsPreferenceFragment implements private String[] mModeValues; private String[] mModeSummaries; - private int mDefaultDayTemperature; - private int mDefaultNightTemperature; - private boolean mHasDisplayModes = false; + private LiveDisplayManager mLiveDisplayManager; + private LiveDisplayConfig mConfig; + private CMHardwareManager mHardware; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final Activity activity = getActivity(); - final ContentResolver resolver = activity.getContentResolver(); final Resources res = getResources(); - mDefaultDayTemperature = res.getInteger( - org.cyanogenmod.platform.internal.R.integer.config_dayColorTemperature); - mDefaultNightTemperature = res.getInteger( - org.cyanogenmod.platform.internal.R.integer.config_nightColorTemperature); - - mHardware = CMHardwareManager.getInstance(activity); + mHardware = CMHardwareManager.getInstance(getActivity()); + mLiveDisplayManager = LiveDisplayManager.getInstance(getActivity()); + mConfig = mLiveDisplayManager.getConfig(); addPreferencesFromResource(R.xml.livedisplay); @@ -130,9 +120,8 @@ public class LiveDisplay extends SettingsPreferenceFragment implements PreferenceCategory advancedPrefs = (PreferenceCategory) findPreference(KEY_CATEGORY_ADVANCED); - int adaptiveMode = CMSettings.System.getIntForUser(resolver, - CMSettings.System.DISPLAY_TEMPERATURE_MODE, - 0, UserHandle.USER_CURRENT); + int adaptiveMode = mLiveDisplayManager.getMode(); + mLiveDisplay = (ListPreference) findPreference(KEY_LIVE_DISPLAY); mLiveDisplay.setValue(String.valueOf(adaptiveMode)); @@ -144,7 +133,7 @@ public class LiveDisplay extends SettingsPreferenceFragment implements org.cyanogenmod.platform.internal.R.array.live_display_summaries); // Remove outdoor mode from lists if there is no support - if (!mHardware.isSupported(FEATURE_SUNLIGHT_ENHANCEMENT)) { + if (!mConfig.hasFeature(LiveDisplayManager.MODE_OUTDOOR)) { int idx = ArrayUtils.indexOf(mModeValues, String.valueOf(MODE_OUTDOOR)); String[] entriesTemp = new String[mModeEntries.length - 1]; String[] valuesTemp = new String[mModeValues.length - 1]; @@ -172,7 +161,7 @@ public class LiveDisplay extends SettingsPreferenceFragment implements mColorProfile = (ListPreference) findPreference(KEY_LIVE_DISPLAY_COLOR_PROFILE); if (liveDisplayPrefs != null && mColorProfile != null - && (!mHardware.isSupported(FEATURE_DISPLAY_MODES) || !updateDisplayModes())) { + && (!mConfig.hasFeature(FEATURE_DISPLAY_MODES) || !updateDisplayModes())) { liveDisplayPrefs.removePreference(mColorProfile); } else { mHasDisplayModes = true; @@ -181,39 +170,37 @@ public class LiveDisplay extends SettingsPreferenceFragment implements mOutdoorMode = (SwitchPreference) findPreference(KEY_LIVE_DISPLAY_AUTO_OUTDOOR_MODE); if (liveDisplayPrefs != null && mOutdoorMode != null - && !mHardware.isSupported(FEATURE_SUNLIGHT_ENHANCEMENT)) { + && !mConfig.hasFeature(MODE_OUTDOOR)) { liveDisplayPrefs.removePreference(mOutdoorMode); mOutdoorMode = null; } mLowPower = (SwitchPreference) findPreference(KEY_LIVE_DISPLAY_LOW_POWER); if (advancedPrefs != null && mLowPower != null - && !mHardware.isSupported(FEATURE_ADAPTIVE_BACKLIGHT)) { + && !mConfig.hasFeature(FEATURE_CABC)) { advancedPrefs.removePreference(mLowPower); mLowPower = null; } mColorEnhancement = (SwitchPreference) findPreference(KEY_LIVE_DISPLAY_COLOR_ENHANCE); if (advancedPrefs != null && mColorEnhancement != null - && !mHardware.isSupported(FEATURE_COLOR_ENHANCEMENT)) { + && !mConfig.hasFeature(FEATURE_COLOR_ENHANCEMENT)) { advancedPrefs.removePreference(mColorEnhancement); mColorEnhancement = null; } - if (advancedPrefs != null - && !mHardware.isSupported(FEATURE_DISPLAY_GAMMA_CALIBRATION)) { - Preference gammaPref = findPreference(KEY_DISPLAY_GAMMA); - if (gammaPref != null) { - advancedPrefs.removePreference(gammaPref); - } + mPictureAdjustment = (PictureAdjustment) findPreference(KEY_PICTURE_ADJUSTMENT); + if (advancedPrefs != null && mPictureAdjustment != null && + !mConfig.hasFeature(LiveDisplayManager.FEATURE_PICTURE_ADJUSTMENT)) { + advancedPrefs.removePreference(mPictureAdjustment); + mPictureAdjustment = null; } - mScreenColorSettings = (PreferenceScreen) findPreference(KEY_SCREEN_COLOR_SETTINGS); - if (advancedPrefs != null) { - if (mScreenColorSettings != null && - (mHasDisplayModes ||!isPostProcessingSupported(getActivity()))) { - advancedPrefs.removePreference(mScreenColorSettings); - } + mDisplayColor = (DisplayColor) findPreference(KEY_DISPLAY_COLOR); + if (advancedPrefs != null && mDisplayColor != null && + !mConfig.hasFeature(LiveDisplayManager.FEATURE_COLOR_ADJUSTMENT)) { + advancedPrefs.removePreference(mDisplayColor); + mDisplayColor = null; } } @@ -254,7 +241,8 @@ public class LiveDisplay extends SettingsPreferenceFragment implements return false; } - final DisplayMode cur = mHardware.getDefaultDisplayMode(); + final DisplayMode cur = mHardware.getCurrentDisplayMode() != null + ? mHardware.getCurrentDisplayMode() : mHardware.getDefaultDisplayMode(); int curId = -1; String[] entries = new String[modes.length]; String[] values = new String[modes.length]; @@ -274,7 +262,7 @@ public class LiveDisplay extends SettingsPreferenceFragment implements mColorProfileSummaries[i] = summary; if (cur != null && modes[i].id == cur.id) { - curId = -1; + curId = cur.id; } } mColorProfile.setEntries(entries); @@ -292,7 +280,8 @@ public class LiveDisplay extends SettingsPreferenceFragment implements } if (value == null) { - DisplayMode cur = mHardware.getDefaultDisplayMode(); + DisplayMode cur = mHardware.getCurrentDisplayMode() != null + ? mHardware.getCurrentDisplayMode() : mHardware.getDefaultDisplayMode(); if (cur != null && cur.id >= 0) { value = String.valueOf(cur.id); } @@ -310,9 +299,7 @@ public class LiveDisplay extends SettingsPreferenceFragment implements } private void updateModeSummary() { - int mode = CMSettings.System.getIntForUser(getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_MODE, - MODE_OFF, UserHandle.USER_CURRENT); + int mode = mLiveDisplayManager.getMode(); int index = ArrayUtils.indexOf(mModeValues, String.valueOf(mode)); if (index < 0) { @@ -331,25 +318,19 @@ public class LiveDisplay extends SettingsPreferenceFragment implements } private void updateTemperatureSummary() { - int day = CMSettings.System.getIntForUser(getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_DAY, - mDefaultDayTemperature, - UserHandle.USER_CURRENT); - int night = CMSettings.System.getIntForUser(getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_NIGHT, - mDefaultNightTemperature, - UserHandle.USER_CURRENT); + int day = mLiveDisplayManager.getDayColorTemperature(); + int night = mLiveDisplayManager.getNightColorTemperature(); mDisplayTemperature.setSummary(getResources().getString( - R.string.live_display_color_temperature_summary, day, night)); + R.string.live_display_color_temperature_summary, + mDisplayTemperature.roundUp(day), + mDisplayTemperature.roundUp(night))); } @Override public boolean onPreferenceChange(Preference preference, Object objValue) { if (preference == mLiveDisplay) { - CMSettings.System.putIntForUser(getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_MODE, - Integer.valueOf((String)objValue), UserHandle.USER_CURRENT); + mLiveDisplayManager.setMode(Integer.valueOf((String)objValue)); } else if (preference == mColorProfile) { int id = Integer.valueOf((String)objValue); Log.i("LiveDisplay", "Setting mode: " + id); @@ -401,8 +382,6 @@ public class LiveDisplay extends SettingsPreferenceFragment implements public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { - private boolean mHasSunlightEnhancement, mHasColorEnhancement, mHasLowPower; - private boolean mHasDisplayGamma; @Override public List<SearchIndexableResource> getXmlResourcesToIndex(Context context, @@ -419,28 +398,27 @@ public class LiveDisplay extends SettingsPreferenceFragment implements @Override public List<String> getNonIndexableKeys(Context context) { - CMHardwareManager hardware = CMHardwareManager.getInstance(context); + final CMHardwareManager hardware = CMHardwareManager.getInstance(context); + final LiveDisplayConfig config = LiveDisplayManager.getInstance(context).getConfig(); ArrayList<String> result = new ArrayList<String>(); if (!hardware.isSupported(FEATURE_DISPLAY_MODES)) { result.add(KEY_LIVE_DISPLAY_COLOR_PROFILE); } - if (!hardware.isSupported(FEATURE_SUNLIGHT_ENHANCEMENT)) { + if (!config.hasFeature(MODE_OUTDOOR)) { result.add(KEY_LIVE_DISPLAY_AUTO_OUTDOOR_MODE); } - if (!hardware.isSupported(FEATURE_COLOR_ENHANCEMENT)) { + if (!config.hasFeature(FEATURE_COLOR_ENHANCEMENT)) { result.add(KEY_LIVE_DISPLAY_COLOR_ENHANCE); } - if (!hardware.isSupported(FEATURE_ADAPTIVE_BACKLIGHT)) { + if (!config.hasFeature(FEATURE_CABC)) { result.add(KEY_LIVE_DISPLAY_LOW_POWER); } - if (!isPostProcessingSupported(context)) { - result.add(KEY_SCREEN_COLOR_SETTINGS); - } else { + if (!config.hasFeature(FEATURE_COLOR_ADJUSTMENT)) { result.add(KEY_DISPLAY_COLOR); } - if (!hardware.isSupported(FEATURE_DISPLAY_GAMMA_CALIBRATION)) { - result.add(KEY_DISPLAY_GAMMA); + if (!config.hasFeature(FEATURE_PICTURE_ADJUSTMENT)) { + result.add(KEY_PICTURE_ADJUSTMENT); } return result; } diff --git a/src/com/android/settings/livedisplay/PictureAdjustment.java b/src/com/android/settings/livedisplay/PictureAdjustment.java new file mode 100644 index 0000000..657d7d4 --- /dev/null +++ b/src/com/android/settings/livedisplay/PictureAdjustment.java @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.livedisplay; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.util.Range; +import android.view.View; +import android.widget.Button; +import android.widget.SeekBar; +import android.widget.TextView; + +import com.android.settings.IntervalSeekBar; +import com.android.settings.R; + +import cyanogenmod.hardware.HSIC; +import cyanogenmod.hardware.LiveDisplayManager; + +import java.util.List; + +/** + * Special preference type that allows configuration of Color settings + */ +public class PictureAdjustment extends DialogPreference { + private static final String TAG = "PictureAdjustment"; + + private final Context mContext; + private final LiveDisplayManager mLiveDisplay; + private final List<Range<Float>> mRanges; + + // These arrays must all match in length and order + private static final int[] SEEKBAR_ID = new int[] { + R.id.adj_hue_seekbar, + R.id.adj_saturation_seekbar, + R.id.adj_intensity_seekbar, + R.id.adj_contrast_seekbar + }; + + private static final int[] SEEKBAR_VALUE_ID = new int[] { + R.id.adj_hue_value, + R.id.adj_saturation_value, + R.id.adj_intensity_value, + R.id.adj_contrast_value + }; + + private ColorSeekBar[] mSeekBars = new ColorSeekBar[SEEKBAR_ID.length]; + + private final float[] mCurrentAdj = new float[5]; + private final float[] mOriginalAdj = new float[5]; + + public PictureAdjustment(Context context, AttributeSet attrs) { + super(context, attrs); + + mContext = context; + mLiveDisplay = LiveDisplayManager.getInstance(mContext); + mRanges = mLiveDisplay.getConfig().getPictureAdjustmentRanges(); + + setDialogLayoutResource(R.layout.display_picture_adjustment); + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + builder.setNeutralButton(R.string.settings_reset_button, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }); + } + + private void updateBars() { + for (int i = 0; i < SEEKBAR_ID.length; i++) { + mSeekBars[i].setValue(mCurrentAdj[i]); + } + } + + @Override + protected void onBindDialogView(View view) { + super.onBindDialogView(view); + + System.arraycopy(mLiveDisplay.getPictureAdjustment().toFloatArray(), 0, mOriginalAdj, 0, 5); + System.arraycopy(mOriginalAdj, 0, mCurrentAdj, 0, 5); + + for (int i = 0; i < SEEKBAR_ID.length; i++) { + IntervalSeekBar seekBar = (IntervalSeekBar) view.findViewById(SEEKBAR_ID[i]); + TextView value = (TextView) view.findViewById(SEEKBAR_VALUE_ID[i]); + final Range<Float> range = mRanges.get(i); + mSeekBars[i] = new ColorSeekBar(seekBar, range, value, i); + } + updateBars(); + } + + @Override + protected void showDialog(Bundle state) { + super.showDialog(state); + + // Can't use onPrepareDialogBuilder for this as we want the dialog + // to be kept open on click + AlertDialog d = (AlertDialog) getDialog(); + Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL); + defaultsButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + System.arraycopy(mLiveDisplay.getDefaultPictureAdjustment().toFloatArray(), + 0, mCurrentAdj, 0, 5); + updateBars(); + updateAdjustment(mCurrentAdj); + } + }); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + updateAdjustment(positiveResult ? mCurrentAdj : mOriginalAdj); + } + + @Override + protected Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + if (getDialog() == null || !getDialog().isShowing()) { + return superState; + } + + // Save the dialog state + final SavedState myState = new SavedState(superState); + myState.currentAdj = mCurrentAdj; + myState.originalAdj = mOriginalAdj; + + // Restore the old state when the activity or dialog is being paused + updateAdjustment(mOriginalAdj); + + return myState; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state == null || !state.getClass().equals(SavedState.class)) { + // Didn't save state for us in onSaveInstanceState + super.onRestoreInstanceState(state); + return; + } + + SavedState myState = (SavedState) state; + super.onRestoreInstanceState(myState.getSuperState()); + + System.arraycopy(myState.originalAdj, 0, mOriginalAdj, 0, 5); + System.arraycopy(myState.currentAdj, 0, mCurrentAdj, 0, 5); + + updateBars(); + updateAdjustment(mCurrentAdj); + } + + private static class SavedState extends BaseSavedState { + float[] originalAdj; + float[] currentAdj; + + public SavedState(Parcelable superState) { + super(superState); + } + + public SavedState(Parcel source) { + super(source); + originalAdj = source.createFloatArray(); + currentAdj = source.createFloatArray(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeFloatArray(originalAdj); + dest.writeFloatArray(currentAdj); + } + + public static final Creator<SavedState> CREATOR = + new Creator<PictureAdjustment.SavedState>() { + + public PictureAdjustment.SavedState createFromParcel(Parcel in) { + return new PictureAdjustment.SavedState(in); + } + + public PictureAdjustment.SavedState[] newArray(int size) { + return new PictureAdjustment.SavedState[size]; + } + }; + } + + private void updateAdjustment(final float[] adjustment) { + mLiveDisplay.setPictureAdjustment(HSIC.fromFloatArray(adjustment)); + } + + private class ColorSeekBar implements SeekBar.OnSeekBarChangeListener { + private int mIndex; + private final IntervalSeekBar mSeekBar; + private TextView mValue; + private Range<Float> mRange; + + public ColorSeekBar(IntervalSeekBar seekBar, Range<Float> range, TextView value, int index) { + mSeekBar = seekBar; + mValue = value; + mIndex = index; + mRange = range; + mSeekBar.setMinimum(range.getLower()); + mSeekBar.setMaximum(range.getUpper()); + + mSeekBar.setOnSeekBarChangeListener(this); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + IntervalSeekBar isb = (IntervalSeekBar)seekBar; + float fp = isb.getProgressFloat(); + if (fromUser) { + mCurrentAdj[mIndex] = mRanges.get(mIndex).clamp(fp); + updateAdjustment(mCurrentAdj); + } + mValue.setText(getLabel(mCurrentAdj[mIndex])); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // Do nothing here + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // Do nothing here + } + + private String getLabel(float value) { + if (mRange.getUpper() == 1.0f) { + return String.format("%d%%", Math.round(100F * value)); + } + return String.format("%d", Math.round(value)); + } + + public void setValue(float value) { + mSeekBar.setProgressFloat(value); + mValue.setText(getLabel(value)); + } + } +} diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java index d54aced..2e76f92 100644 --- a/src/com/android/settings/notification/AppNotificationSettings.java +++ b/src/com/android/settings/notification/AppNotificationSettings.java @@ -27,6 +27,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.UserHandle; +import android.preference.ListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; @@ -59,6 +60,9 @@ public class AppNotificationSettings extends SettingsPreferenceFragment { private static final String KEY_PEEKABLE = "peekable"; private static final String KEY_SENSITIVE = "sensitive"; private static final String KEY_APP_SETTINGS = "app_settings"; + private static final String KEY_SHOW_ON_KEYGUARD = "show_on_keyguard"; + private static final String KEY_NO_ONGOING_ON_KEYGUARD = "no_ongoing_on_keyguard"; + private static final String KEY_SOUND_TIMEOUT = "sound_timeout"; private static final Intent APP_NOTIFICATION_PREFS_CATEGORY_INTENT = new Intent(Intent.ACTION_MAIN) @@ -71,6 +75,9 @@ public class AppNotificationSettings extends SettingsPreferenceFragment { private SwitchPreference mPriority; private SwitchPreference mPeekable; private SwitchPreference mSensitive; + private SwitchPreference mShowOnKeyguard; + private SwitchPreference mShowNoOngoingOnKeyguard; + private ListPreference mSoundTimeout; private AppRow mAppRow; private boolean mCreated; private boolean mIsSystemPackage; @@ -137,6 +144,9 @@ public class AppNotificationSettings extends SettingsPreferenceFragment { mPriority = (SwitchPreference) findPreference(KEY_PRIORITY); mPeekable = (SwitchPreference) findPreference(KEY_PEEKABLE); mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE); + mShowOnKeyguard = (SwitchPreference) findPreference(KEY_SHOW_ON_KEYGUARD); + mShowNoOngoingOnKeyguard = (SwitchPreference) findPreference(KEY_NO_ONGOING_ON_KEYGUARD); + mSoundTimeout = (ListPreference) findPreference(KEY_SOUND_TIMEOUT); mAppRow = mBackend.loadAppRow(pm, info.applicationInfo); @@ -150,6 +160,8 @@ public class AppNotificationSettings extends SettingsPreferenceFragment { mPriority.setChecked(mAppRow.priority); mPeekable.setChecked(mAppRow.peekable); mSensitive.setChecked(mAppRow.sensitive); + mSoundTimeout.setValue(Long.toString(mAppRow.soundTimeout)); + updateSoundTimeoutSummary(mAppRow.soundTimeout); mBlock.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override @@ -190,6 +202,18 @@ public class AppNotificationSettings extends SettingsPreferenceFragment { } }); + mSoundTimeout.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + long value = Long.valueOf((String) newValue); + if (!mBackend.setNotificationSoundTimeout(pkg, mUid, value)) { + return false; + } + updateSoundTimeoutSummary(value); + return true; + } + }); + if (mAppRow.settingsIntent != null) { findPreference(KEY_APP_SETTINGS).setOnPreferenceClickListener( new OnPreferenceClickListener() { @@ -202,6 +226,47 @@ public class AppNotificationSettings extends SettingsPreferenceFragment { } else { removePreference(KEY_APP_SETTINGS); } + + int keyguard = mBackend.getShowNotificationForPackageOnKeyguard(pkg, mUid); + mShowOnKeyguard.setChecked((keyguard & Notification.SHOW_ALL_NOTI_ON_KEYGUARD) != 0); + mShowNoOngoingOnKeyguard.setChecked( + (keyguard & Notification.SHOW_NO_ONGOING_NOTI_ON_KEYGUARD) != 0); + + mShowOnKeyguard.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final boolean showOnKeyguard = (Boolean) newValue; + int keyguard = mBackend.getShowNotificationForPackageOnKeyguard(pkg, mUid); + + if (showOnKeyguard && (keyguard & Notification.SHOW_ALL_NOTI_ON_KEYGUARD) == 0) { + keyguard |= Notification.SHOW_ALL_NOTI_ON_KEYGUARD; + } else { + keyguard &= ~Notification.SHOW_ALL_NOTI_ON_KEYGUARD; + } + return mBackend.setShowNotificationForPackageOnKeyguard(pkg, mUid, keyguard); + } + }); + + mShowNoOngoingOnKeyguard.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final boolean showNoOngoingOnKeyguard = (Boolean) newValue; + int keyguard = mBackend.getShowNotificationForPackageOnKeyguard(pkg, mUid); + if (showNoOngoingOnKeyguard + && (keyguard & Notification.SHOW_NO_ONGOING_NOTI_ON_KEYGUARD) == 0) { + keyguard |= Notification.SHOW_NO_ONGOING_NOTI_ON_KEYGUARD; + } else { + keyguard &= ~Notification.SHOW_NO_ONGOING_NOTI_ON_KEYGUARD; + } + return mBackend.setShowNotificationForPackageOnKeyguard(pkg, mUid, keyguard); + } + }); + + // Users cannot block notifications from system/signature packages + if (mIsSystemPackage || !getLockscreenNotificationsEnabled()) { + getPreferenceScreen().removePreference(mShowNoOngoingOnKeyguard); + getPreferenceScreen().removePreference(mShowOnKeyguard); + } } @Override @@ -213,6 +278,25 @@ public class AppNotificationSettings extends SettingsPreferenceFragment { } } + private void updateSoundTimeoutSummary(long value) { + if (value == 0) { + mSoundTimeout.setSummary(R.string.app_notification_sound_timeout_value_none); + } else { + final CharSequence[] entries = mSoundTimeout.getEntries(); + final CharSequence[] values = mSoundTimeout.getEntryValues(); + CharSequence summary = null; + for (int i = 0; i < values.length; i++) { + long timeout = Long.parseLong(values[i].toString()); + if (timeout == value) { + summary = getString(R.string.app_notification_sound_timeout_summary_template, + entries[i]); + break; + } + } + mSoundTimeout.setSummary(summary); + } + } + private void updateDependents(boolean banned) { final boolean lockscreenSecure = new LockPatternUtils(getActivity()).isSecure( UserHandle.myUserId()); @@ -226,6 +310,8 @@ public class AppNotificationSettings extends SettingsPreferenceFragment { setVisible(mPeekable, mIsSystemPackage || !banned && headsUpEnabled); setVisible(mSensitive, mIsSystemPackage || !banned && lockscreenSecure && lockscreenNotificationsEnabled && allowPrivate); + setVisible(mShowOnKeyguard, mIsSystemPackage || !banned); + setVisible(mShowNoOngoingOnKeyguard, mIsSystemPackage || !banned); } private void setVisible(Preference p, boolean visible) { diff --git a/src/com/android/settings/notification/IncreasingRingVolumePreference.java b/src/com/android/settings/notification/IncreasingRingVolumePreference.java index 6b78bbe..8a55eaa 100644 --- a/src/com/android/settings/notification/IncreasingRingVolumePreference.java +++ b/src/com/android/settings/notification/IncreasingRingVolumePreference.java @@ -143,6 +143,8 @@ public class IncreasingRingVolumePreference extends Preference implements mStartVolumeSeekBar.setOnSeekBarChangeListener(this); mRampUpTimeSeekBar.setOnSeekBarChangeListener(this); mRampUpTimeSeekBar.setProgress((rampUpTime / 5) - 1); + mRampUpTimeValue.setText( + Formatter.formatShortElapsedTime(getContext(), rampUpTime * 1000)); } @Override diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java index 2060719..ae83179 100644 --- a/src/com/android/settings/notification/NotificationBackend.java +++ b/src/com/android/settings/notification/NotificationBackend.java @@ -47,6 +47,7 @@ public class NotificationBackend { row.priority = getHighPriority(row.pkg, row.uid); row.peekable = getPeekable(row.pkg, row.uid); row.sensitive = getSensitive(row.pkg, row.uid); + row.soundTimeout = getNotificationSoundTimeout(row.pkg, row.uid); return row; } @@ -130,6 +131,44 @@ public class NotificationBackend { } } + public int getShowNotificationForPackageOnKeyguard(String pkg, int uid) { + try { + return sINM.getShowNotificationForPackageOnKeyguard(pkg, uid); + } catch (Exception e) { + Log.w(TAG, "Error calling NoMan", e); + return Notification.SHOW_ALL_NOTI_ON_KEYGUARD; + } + } + + public boolean setShowNotificationForPackageOnKeyguard(String pkg, int uid, int status) { + try { + sINM.setShowNotificationForPackageOnKeyguard(pkg, uid, status); + return true; + } catch (Exception e) { + Log.w(TAG, "Error calling NoMan", e); + return false; + } + } + + public long getNotificationSoundTimeout(String pkg, int uid) { + try { + return sINM.getPackageNotificationSoundTimeout(pkg, uid); + } catch (Exception e) { + Log.w(TAG, "Error calling NoMan", e); + return 0; + } + } + + public boolean setNotificationSoundTimeout(String pkg, int uid, long timeout) { + try { + sINM.setPackageNotificationSoundTimeout(pkg, uid, timeout); + return true; + } catch (Exception e) { + Log.w(TAG, "Error calling NoMan", e); + return false; + } + } + static class Row { public String section; } @@ -145,6 +184,7 @@ public class NotificationBackend { public boolean peekable; public boolean sensitive; public boolean first; // first app in section + public long soundTimeout; } } diff --git a/src/com/android/settings/notification/ZenModePrioritySettings.java b/src/com/android/settings/notification/ZenModePrioritySettings.java index e8a8bb1..08e0350 100644 --- a/src/com/android/settings/notification/ZenModePrioritySettings.java +++ b/src/com/android/settings/notification/ZenModePrioritySettings.java @@ -28,6 +28,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.settings.DropDownPreference; import com.android.settings.R; import com.android.settings.search.Indexable; +import cyanogenmod.providers.CMSettings; public class ZenModePrioritySettings extends ZenModeSettingsBase implements Indexable { private static final String KEY_REMINDERS = "reminders"; @@ -35,6 +36,7 @@ public class ZenModePrioritySettings extends ZenModeSettingsBase implements Inde private static final String KEY_MESSAGES = "messages"; private static final String KEY_CALLS = "calls"; private static final String KEY_REPEAT_CALLERS = "repeat_callers"; + private static final String KEY_VIBRATION = "vibration"; private static final String KEY_ALLOW_LIGHTS = "zen_priority_allow_lights"; private static final int SOURCE_NONE = -1; @@ -146,6 +148,21 @@ public class ZenModePrioritySettings extends ZenModeSettingsBase implements Inde } }); + DropDownPreference vibration = (DropDownPreference) root.findPreference(KEY_VIBRATION); + vibration.addItem(R.string.zen_mode_vibration_never, null); + vibration.addItem(R.string.zen_mode_vibration_calls_only, null); + vibration.addItem(R.string.zen_mode_vibration_calls_and_notifications, null); + vibration.setSelectedItem(CMSettings.System.getInt(getContentResolver(), + CMSettings.System.ZEN_PRIORITY_VIBRATION_MODE, 0)); + vibration.setCallback(new DropDownPreference.Callback() { + @Override + public boolean onItemSelected(int pos, Object newValue) { + CMSettings.System.putInt(getContentResolver(), + CMSettings.System.ZEN_PRIORITY_VIBRATION_MODE, pos); + return true; + } + }); + // Remove of the "Allow notification light" setting if LED is not supported if (!getResources().getBoolean( com.android.internal.R.bool.config_intrusiveNotificationLed)) { diff --git a/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java b/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java index 3e88046..a0af03f 100644 --- a/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java +++ b/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java @@ -61,8 +61,9 @@ public class ZenModeScheduleDaysSelection extends ScrollView { } mLayout.setOrientation(LinearLayout.VERTICAL); final Calendar c = Calendar.getInstance(); + int i = c.getFirstDayOfWeek() - 1; final LayoutInflater inflater = LayoutInflater.from(context); - for (int i = 0; i < DAYS.length; i++) { + for (int d = 0; d < DAYS.length; d++) { final int day = DAYS[i]; final CheckBox checkBox = (CheckBox) inflater.inflate(R.layout.zen_schedule_rule_day, this, false); @@ -77,6 +78,7 @@ public class ZenModeScheduleDaysSelection extends ScrollView { } }); mLayout.addView(checkBox); + i = ++i % DAYS.length; } } diff --git a/src/com/android/settings/notificationlight/ApplicationLightPreference.java b/src/com/android/settings/notificationlight/ApplicationLightPreference.java index a12f45b..405c826 100644 --- a/src/com/android/settings/notificationlight/ApplicationLightPreference.java +++ b/src/com/android/settings/notificationlight/ApplicationLightPreference.java @@ -18,6 +18,7 @@ package com.android.settings.notificationlight; import android.app.AlertDialog; import android.app.Dialog; +import android.app.NotificationManager; import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; @@ -55,11 +56,11 @@ public class ApplicationLightPreference extends DialogPreference { */ public ApplicationLightPreference(Context context, AttributeSet attrs) { super(context, attrs); + NotificationManager nm = context.getSystemService(NotificationManager.class); mColorValue = DEFAULT_COLOR; mOnValue = DEFAULT_TIME; mOffValue = DEFAULT_TIME; - mOnOffChangeable = context.getResources().getBoolean( - com.android.internal.R.bool.config_ledCanPulse); + mOnOffChangeable = nm.deviceLightsCan(NotificationManager.LIGHTS_LED_PULSE); init(); } @@ -71,11 +72,11 @@ public class ApplicationLightPreference extends DialogPreference { */ public ApplicationLightPreference(Context context, int color, int onValue, int offValue) { super(context, null); + NotificationManager nm = context.getSystemService(NotificationManager.class); mColorValue = color; mOnValue = onValue; mOffValue = offValue; - mOnOffChangeable = context.getResources().getBoolean( - com.android.internal.R.bool.config_ledCanPulse); + mOnOffChangeable = nm.deviceLightsCan(NotificationManager.LIGHTS_LED_PULSE); init(); } @@ -117,6 +118,8 @@ public class ApplicationLightPreference extends DialogPreference { protected void onBindView(View view) { super.onBindView(view); + NotificationManager nm = getContext().getSystemService(NotificationManager.class); + mLightColorView = (ImageView) view.findViewById(R.id.light_color); mOnValueView = (TextView) view.findViewById(R.id.textViewTimeOnValue); mOffValueView = (TextView) view.findViewById(R.id.textViewTimeOffValue); @@ -126,7 +129,7 @@ public class ApplicationLightPreference extends DialogPreference { TextView tView = (TextView) view.findViewById(android.R.id.summary); tView.setVisibility(View.GONE); - if (!mResources.getBoolean(com.android.internal.R.bool.config_multiColorNotificationLed)) { + if (!nm.deviceLightsCan(NotificationManager.LIGHTS_RGB_NOTIFICATION)) { mLightColorView.setVisibility(View.GONE); } diff --git a/src/com/android/settings/notificationlight/BatteryLightSettings.java b/src/com/android/settings/notificationlight/BatteryLightSettings.java index 80d7fa2..afdd756 100644 --- a/src/com/android/settings/notificationlight/BatteryLightSettings.java +++ b/src/com/android/settings/notificationlight/BatteryLightSettings.java @@ -16,6 +16,7 @@ package com.android.settings.notificationlight; +import android.app.NotificationManager; import android.content.ContentResolver; import android.content.res.Resources; import android.os.Bundle; @@ -64,6 +65,8 @@ public class BatteryLightSettings extends SettingsPreferenceFragment implements super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.battery_light_settings); + final NotificationManager nm = getContext().getSystemService(NotificationManager.class); + PreferenceScreen prefSet = getPreferenceScreen(); PreferenceGroup mGeneralPrefs = (PreferenceGroup) prefSet.findPreference("general_section"); @@ -71,12 +74,13 @@ public class BatteryLightSettings extends SettingsPreferenceFragment implements mLightEnabledPref = (CMSystemSettingSwitchPreference) prefSet.findPreference(LIGHT_ENABLED_PREF); mPulseEnabledPref = (CMSystemSettingSwitchPreference) prefSet.findPreference(PULSE_ENABLED_PREF); - if (!getResources().getBoolean(com.android.internal.R.bool.config_ledCanPulse)) { + if (!nm.deviceLightsCan(NotificationManager.LIGHTS_LED_PULSE) || + nm.deviceLightsCan(NotificationManager.LIGHTS_SEGMENTED_BATTERY_LIGHTS) ) { mGeneralPrefs.removePreference(mPulseEnabledPref); } // Does the Device support changing battery LED colors? - if (getResources().getBoolean(com.android.internal.R.bool.config_multiColorBatteryLed)) { + if (nm.deviceLightsCan(NotificationManager.LIGHTS_RGB_BATTERY)) { setHasOptionsMenu(true); // Low, Medium and full color preferences @@ -143,10 +147,14 @@ public class BatteryLightSettings extends SettingsPreferenceFragment implements @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - menu.add(0, MENU_RESET, 0, R.string.profile_reset_title) - .setIcon(R.drawable.ic_settings_backup_restore) - .setAlphabeticShortcut('r') - .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + final NotificationManager nm = getContext().getSystemService(NotificationManager.class); + if (nm.deviceLightsCan(NotificationManager.LIGHTS_RGB_BATTERY)) { + menu.add(0, MENU_RESET, 0, R.string.profile_reset_title) + .setIcon(R.drawable.ic_settings_backup_restore) + .setAlphabeticShortcut('r') + .setShowAsActionFlags( + MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + } } @Override diff --git a/src/com/android/settings/notificationlight/LightSettingsDialog.java b/src/com/android/settings/notificationlight/LightSettingsDialog.java index d2d4e84..79b23e0 100644 --- a/src/com/android/settings/notificationlight/LightSettingsDialog.java +++ b/src/com/android/settings/notificationlight/LightSettingsDialog.java @@ -170,8 +170,7 @@ public class LightSettingsDialog extends AlertDialog implements setView(layout); setTitle(R.string.edit_light_settings); - if (!getContext().getResources().getBoolean( - com.android.internal.R.bool.config_multiColorNotificationLed)) { + if (!mNotificationManager.deviceLightsCan(NotificationManager.LIGHTS_RGB_NOTIFICATION)) { mColorPicker.setVisibility(View.GONE); mColorPanel.setVisibility(View.GONE); mLightsDialogDivider.setVisibility(View.GONE); diff --git a/src/com/android/settings/notificationlight/NotificationLightSettings.java b/src/com/android/settings/notificationlight/NotificationLightSettings.java index 95a354d..3b02d36 100644 --- a/src/com/android/settings/notificationlight/NotificationLightSettings.java +++ b/src/com/android/settings/notificationlight/NotificationLightSettings.java @@ -18,6 +18,7 @@ package com.android.settings.notificationlight; import android.app.AlertDialog; import android.app.Dialog; +import android.app.NotificationManager; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; @@ -88,6 +89,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem private String mPackageList; private Map<String, Package> mPackages; private boolean mMultiColorLed; + private boolean mLedCanPulse; @Override public void onCreate(Bundle savedInstanceState) { @@ -97,7 +99,10 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem PreferenceScreen prefSet = getPreferenceScreen(); Resources resources = getResources(); + final NotificationManager nm = getContext().getSystemService(NotificationManager.class); + PreferenceGroup mAdvancedPrefs = (PreferenceGroup) prefSet.findPreference("advanced_section"); + PreferenceGroup mGeneralPrefs = (PreferenceGroup) prefSet.findPreference("general_section"); // Get the system defined default notification color mDefaultColor = @@ -108,12 +113,14 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem mDefaultLedOff = resources.getInteger( com.android.internal.R.integer.config_defaultNotificationLedOff); + mLedCanPulse = nm.deviceLightsCan(NotificationManager.LIGHTS_LED_PULSE); + mMultiColorLed = nm.deviceLightsCan(NotificationManager.LIGHTS_RGB_NOTIFICATION); + mEnabledPref = (SystemSettingSwitchPreference) findPreference(Settings.System.NOTIFICATION_LIGHT_PULSE); mEnabledPref.setOnPreferenceChangeListener(this); mDefaultPref = (ApplicationLightPreference) findPreference(DEFAULT_PREF); - mDefaultPref.setOnPreferenceChangeListener(this); mAutoGenerateColors = (CMSystemSettingSwitchPreference) findPreference(CMSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO); @@ -128,23 +135,29 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem mScreenOnLightsPref.setOnPreferenceChangeListener(this); mCustomEnabledPref = (CMSystemSettingSwitchPreference) findPreference(CMSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE); - mCustomEnabledPref.setOnPreferenceChangeListener(this); if (!resources.getBoolean( org.cyanogenmod.platform.internal.R.bool.config_adjustableNotificationLedBrightness)) { mAdvancedPrefs.removePreference(mNotificationLedBrightnessPref); } else { mNotificationLedBrightnessPref.setOnPreferenceChangeListener(this); } - if (!resources.getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_multipleNotificationLeds)) { + if (!nm.deviceLightsCan(NotificationManager.LIGHTS_MULTIPLE_LED)) { mAdvancedPrefs.removePreference(mMultipleLedsEnabledPref); } else { mMultipleLedsEnabledPref.setOnPreferenceChangeListener(this); } + if (!mLedCanPulse && !mMultiColorLed) { + mGeneralPrefs.removePreference(mDefaultPref); + mAdvancedPrefs.removePreference(mCustomEnabledPref); + } else { + mCustomEnabledPref.setOnPreferenceChangeListener(this); + mDefaultPref.setOnPreferenceChangeListener(this); + } // Missed call and Voicemail preferences should only show on devices with a voice capabilities TelephonyManager tm = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); - if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) { + if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE + || (!mLedCanPulse && !mMultiColorLed)) { removePreference("phone_list"); } else { mCallPref = (ApplicationLightPreference) findPreference(MISSED_CALL_PREF); @@ -154,8 +167,12 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem mVoicemailPref.setOnPreferenceChangeListener(this); } - mApplicationPrefList = (PreferenceGroup) findPreference("applications_list"); - mApplicationPrefList.setOrderingAsAdded(false); + if (!mLedCanPulse && !mMultiColorLed) { + removePreference("applications_list"); + } else { + mApplicationPrefList = (PreferenceGroup) findPreference("applications_list"); + mApplicationPrefList.setOrderingAsAdded(false); + } // Get launch-able applications mPackageManager = getPackageManager(); @@ -164,10 +181,8 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem mPackages = new HashMap<String, Package>(); setHasOptionsMenu(true); - mMultiColorLed = resources.getBoolean(com.android.internal.R.bool.config_multiColorNotificationLed); if (!mMultiColorLed) { resetColors(); - PreferenceGroup mGeneralPrefs = (PreferenceGroup) prefSet.findPreference("general_section"); mGeneralPrefs.removePreference(mAutoGenerateColors); } else { mAutoGenerateColors.setOnPreferenceChangeListener(this); @@ -251,8 +266,10 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem mVoicemailPref.setAllValues(vmailColor, vmailTimeOn, vmailTimeOff); } - mApplicationPrefList = (PreferenceGroup) findPreference("applications_list"); - mApplicationPrefList.setOrderingAsAdded(false); + if (mLedCanPulse || mMultiColorLed) { + mApplicationPrefList = (PreferenceGroup) findPreference("applications_list"); + mApplicationPrefList.setOrderingAsAdded(false); + } } private void refreshCustomApplicationPrefs() { @@ -284,6 +301,18 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem // Do nothing } } + + /* Display a pref explaining how to add apps */ + if (mApplicationPrefList.getPreferenceCount() == 0) { + String summary = getResources().getString( + R.string.notification_light_no_apps_summary); + String useCustom = getResources().getString( + R.string.notification_light_use_custom); + Preference pref = new Preference(context); + pref.setSummary(String.format(summary, useCustom)); + pref.setEnabled(false); + mApplicationPrefList.addPreference(pref); + } } } diff --git a/src/com/android/settings/privacyguard/PrivacyGuardManager.java b/src/com/android/settings/privacyguard/PrivacyGuardManager.java index adbe8cc..c2f485a 100644 --- a/src/com/android/settings/privacyguard/PrivacyGuardManager.java +++ b/src/com/android/settings/privacyguard/PrivacyGuardManager.java @@ -17,6 +17,7 @@ package com.android.settings.privacyguard; import android.app.FragmentTransaction; +import android.os.Build; import android.view.animation.AnimationUtils; import android.app.Activity; import android.app.AlertDialog; @@ -297,9 +298,9 @@ public class PrivacyGuardManager extends Fragment return true; } - private boolean shouldShowSystemApps() { - return mPreferences.getBoolean("show_system_apps", false); + return mPreferences.getBoolean("show_system_apps", true) && + mActivity.getResources().getBoolean(R.bool.config_showBuiltInAppsForPG); } public static class HelpDialogFragment extends DialogFragment { @@ -372,7 +373,11 @@ public class PrivacyGuardManager extends Fragment public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.privacy_guard_manager, menu); - menu.findItem(R.id.show_system_apps).setChecked(shouldShowSystemApps()); + if (!mActivity.getResources().getBoolean(R.bool.config_showBuiltInAppsForPG)) { + menu.removeItem(R.id.show_system_apps); + } else { + menu.findItem(R.id.show_system_apps).setChecked(shouldShowSystemApps()); + } } @Override diff --git a/src/com/android/settings/privacyguard/PrivacyGuardPrefs.java b/src/com/android/settings/privacyguard/PrivacyGuardPrefs.java index d2417a3..060e617 100644 --- a/src/com/android/settings/privacyguard/PrivacyGuardPrefs.java +++ b/src/com/android/settings/privacyguard/PrivacyGuardPrefs.java @@ -55,7 +55,7 @@ public class PrivacyGuardPrefs extends SettingsPreferenceFragment implements mPrivacyGuardDefault = (SwitchPreference) findPreference(KEY_PRIVACY_GUARD_DEFAULT); mPrivacyGuardDefault.setOnPreferenceChangeListener(this); - mPrivacyGuardDefault.setChecked(Settings.Secure.getInt(getContentResolver(), + mPrivacyGuardDefault.setChecked(CMSettings.Secure.getInt(getContentResolver(), CMSettings.Secure.PRIVACY_GUARD_DEFAULT, 0) == 1); } @@ -75,7 +75,7 @@ public class PrivacyGuardPrefs extends SettingsPreferenceFragment implements public boolean onPreferenceChange(Preference preference, Object newValue) { if (preference == mPrivacyGuardDefault) { boolean value = (Boolean) newValue; - Settings.Secure.putInt(getContentResolver(), + CMSettings.Secure.putInt(getContentResolver(), CMSettings.Secure.PRIVACY_GUARD_DEFAULT, value ? 1 : 0); return true; } diff --git a/src/com/android/settings/profiles/SetupActionsFragment.java b/src/com/android/settings/profiles/SetupActionsFragment.java index d1ca91b..b94632a 100644 --- a/src/com/android/settings/profiles/SetupActionsFragment.java +++ b/src/com/android/settings/profiles/SetupActionsFragment.java @@ -230,7 +230,7 @@ public class SetupActionsFragment extends SettingsPreferenceFragment final List<SubscriptionInfo> subs = SubscriptionManager.from(getContext()) .getActiveSubscriptionInfoList(); - if (subs != null && subs.size() > 1) { + if (subs != null) { for (SubscriptionInfo sub : subs) { mItems.add(generatePreferredNetworkOverrideItem(sub.getSubscriptionId())); } diff --git a/src/com/android/settings/profiles/actions/item/VolumeStreamItem.java b/src/com/android/settings/profiles/actions/item/VolumeStreamItem.java index 9bcf2ef..f4d76c7 100644 --- a/src/com/android/settings/profiles/actions/item/VolumeStreamItem.java +++ b/src/com/android/settings/profiles/actions/item/VolumeStreamItem.java @@ -17,6 +17,7 @@ package com.android.settings.profiles.actions.item; import android.content.Context; import android.media.AudioManager; +import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -30,6 +31,7 @@ import com.android.settings.profiles.actions.ItemListAdapter; public class VolumeStreamItem implements Item { private int mStreamId; private StreamSettings mStreamSettings; + private boolean mEnabled; public VolumeStreamItem(int streamId, StreamSettings streamSettings) { mStreamId = streamId; @@ -43,7 +45,7 @@ public class VolumeStreamItem implements Item { @Override public boolean isEnabled() { - return true; + return mEnabled; } @Override @@ -72,6 +74,15 @@ public class VolumeStreamItem implements Item { desc.setText(context.getString(R.string.profile_action_none)); } + final boolean volumeLinkNotification = Settings.Secure.getInt(context + .getContentResolver(), Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1; + mEnabled = true; + if (mStreamId == AudioManager.STREAM_NOTIFICATION && volumeLinkNotification) { + mEnabled = false; + text.setEnabled(false); + desc.setEnabled(false); + } + return view; } diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java index c58923f..055c2d8 100644 --- a/src/com/android/settings/search/Index.java +++ b/src/com/android/settings/search/Index.java @@ -31,6 +31,7 @@ import android.database.DatabaseUtils; import android.database.MergeCursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; +import android.database.sqlite.SQLiteFullException; import android.net.Uri; import android.os.AsyncTask; import android.provider.SearchIndexableData; @@ -1189,14 +1190,15 @@ public class Index { final boolean forceUpdate = params[0].forceUpdate; - final SQLiteDatabase database = getWritableDatabase(); - if (database == null) { - Log.e(LOG_TAG, "Cannot update Index as I cannot get a writable database"); - return null; - } - final String localeStr = Locale.getDefault().toString(); + SQLiteDatabase database = null; try { + database = getWritableDatabase(); + if (database == null) { + Log.e(LOG_TAG, "Cannot update Index as I cannot get a writable database"); + return null; + } + final String localeStr = Locale.getDefault().toString(); database.beginTransaction(); if (dataToDelete.size() > 0) { processDataToDelete(database, localeStr, dataToDelete); @@ -1206,8 +1208,19 @@ public class Index { forceUpdate); } database.setTransactionSuccessful(); + } catch (SQLiteFullException e) { + Log.e(LOG_TAG, "SQLite database is full." + e.toString()); + } catch (SQLiteException e) { + Log.e(LOG_TAG, e.toString()); } finally { - database.endTransaction(); + try { + if (database != null) + database.endTransaction(); + } catch (SQLiteFullException e) { + Log.e(LOG_TAG, "SQLite database is full." + e.toString()); + } catch (SQLiteException e) { + Log.e(LOG_TAG, e.toString()); + } } return null; diff --git a/src/com/android/settings/search/IndexDatabaseHelper.java b/src/com/android/settings/search/IndexDatabaseHelper.java index 84a2922..146c640 100644 --- a/src/com/android/settings/search/IndexDatabaseHelper.java +++ b/src/com/android/settings/search/IndexDatabaseHelper.java @@ -28,7 +28,7 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper { private static final String TAG = "IndexDatabaseHelper"; private static final String DATABASE_NAME = "search_index.db"; - private static final int DATABASE_VERSION = 118; + private static final int DATABASE_VERSION = 121; public interface Tables { public static final String TABLE_PREFS_INDEX = "prefs_index"; diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java index afd48ae..683aaec 100644 --- a/src/com/android/settings/search/SearchIndexableResources.java +++ b/src/com/android/settings/search/SearchIndexableResources.java @@ -101,7 +101,7 @@ public final class SearchIndexableResources { Ranking.getRankForClassName(SimSettings.class.getName()), NO_DATA_RES_ID, SimSettings.class.getName(), - R.drawable.ic_sim_sd)); + R.drawable.ic_settings_sim)); sResMap.put(DataUsageSummary.class.getName(), new SearchIndexableResource( diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java index 0b73d65..b4c7f03 100644 --- a/src/com/android/settings/sim/SimDialogActivity.java +++ b/src/com/android/settings/sim/SimDialogActivity.java @@ -21,6 +21,8 @@ import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Bundle; import android.os.RemoteException; @@ -45,6 +47,7 @@ import android.widget.TextView; import android.widget.Toast; import com.android.internal.telephony.IExtTelephony; +import com.android.internal.telephony.SmsApplication; import com.android.settings.R; import com.android.settings.Utils; import java.util.ArrayList; @@ -62,6 +65,8 @@ public class SimDialogActivity extends Activity { public static final int SMS_PICK = 2; public static final int PREFERRED_PICK = 3; + private boolean mHideAlwaysAsk = false; + private IExtTelephony mExtTelephony = IExtTelephony.Stub. asInterface(ServiceManager.getService("extphone")); @@ -70,6 +75,7 @@ public class SimDialogActivity extends Activity { super.onCreate(savedInstanceState); final Bundle extras = getIntent().getExtras(); final int dialogType = extras.getInt(DIALOG_TYPE_KEY, INVALID_PICK); + mHideAlwaysAsk = !SmsApplication.canSmsAppHandleAlwaysAsk(this) && dialogType == SMS_PICK; switch (dialogType) { case DATA_PICK: @@ -194,7 +200,8 @@ public class SimDialogActivity extends Activity { case SMS_PICK: boolean isSmsPrompt = false; if (value < 1) { - isSmsPrompt = true; + isSmsPrompt = false; // user knows best + setDefaultSmsSubId(context, SubscriptionManager.INVALID_SUBSCRIPTION_ID); } else { sir = smsSubInfoList.get(value); if ( sir != null) { @@ -238,7 +245,7 @@ public class SimDialogActivity extends Activity { } }; - int currentIndex = -1; + int currentIndex = 0; ArrayList<SubscriptionInfo> callsSubInfoList = new ArrayList<SubscriptionInfo>(); if (id == CALLS_PICK) { final TelecomManager telecomManager = TelecomManager.from(context); @@ -294,8 +301,13 @@ public class SimDialogActivity extends Activity { currentIndex = list.size() - 1; } } + if (mHideAlwaysAsk && currentIndex == 0) { + // unselect always ask because user can't select it. + currentIndex = -1; + } } else { - SubscriptionInfo defaultSub = subscriptionManager.getDefaultDataSubscriptionInfo(); + currentIndex = -1; + final int defaultDataSubId = SubscriptionManager.getDefaultDataSubId(); for (int i = 0; i < selectableSubInfoLength; ++i) { final SubscriptionInfo sir = subInfoList.get(i); CharSequence displayName = sir.getDisplayName(); @@ -303,8 +315,7 @@ public class SimDialogActivity extends Activity { displayName = ""; } list.add(displayName.toString()); - if (defaultSub != null && defaultSub.getSubscriptionId() - == sir.getSubscriptionId()) { + if (defaultDataSubId == sir.getSubscriptionId()) { currentIndex = list.size() - 1; } } @@ -344,6 +355,11 @@ public class SimDialogActivity extends Activity { finish(); } }); + if (mHideAlwaysAsk) { + // make sure the user doesn't click out accidentally and we keep spamming them + // with dialogs + dialog.setCancelable(false); + } return dialog; @@ -357,6 +373,16 @@ public class SimDialogActivity extends Activity { private List<SubscriptionInfo> mSubInfoList; private final int mSelectionIndex; + @Override + public boolean areAllItemsEnabled() { + return false; + } + + @Override + public boolean isEnabled(int position) { + return !(mHideAlwaysAsk && mSubInfoList.get(position) == null); + } + public SelectAccountListAdapter(List<SubscriptionInfo> subInfoList, Context context, int resource, String[] arr, int dialogId, int selectionIndex) { super(context, resource, arr); @@ -388,10 +414,14 @@ public class SimDialogActivity extends Activity { holder = (ViewHolder) rowView.getTag(); } + final boolean enabled = isEnabled(position); final SubscriptionInfo sir = mSubInfoList.get(position); if (sir == null) { holder.title.setText(getItem(position)); - holder.summary.setVisibility(View.GONE); + holder.summary.setText(mHideAlwaysAsk + ? getString(R.string.not_available_with_app, getCurrentSmsAppName()) + : null); + holder.summary.setVisibility(View.VISIBLE); holder.icon.setImageDrawable(getResources() .getDrawable(R.drawable.ic_live_help)); holder.icon.setAlpha(OPACITY); @@ -402,9 +432,24 @@ public class SimDialogActivity extends Activity { holder.icon.setImageBitmap(sir.createIconBitmap(mContext)); } holder.radio.setChecked(position == mSelectionIndex); + holder.radio.setEnabled(enabled); + holder.title.setEnabled(enabled); + holder.summary.setEnabled(enabled); return rowView; } + private String getCurrentSmsAppName() { + try { + final ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo( + SmsApplication.getDefaultMmsApplication(getApplicationContext(), false) + .getPackageName(), 0); + return getPackageManager().getApplicationLabel(applicationInfo).toString(); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } + private class ViewHolder { TextView title; TextView summary; diff --git a/src/com/android/settings/sim/SimSettings.java b/src/com/android/settings/sim/SimSettings.java index 20a401e..b97ee03 100644 --- a/src/com/android/settings/sim/SimSettings.java +++ b/src/com/android/settings/sim/SimSettings.java @@ -28,6 +28,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.graphics.drawable.BitmapDrawable; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -511,11 +512,12 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable // Disable manual provisioning option to user when // device is in Airplane mode. Hide it if the extphone framework // is not present, as the operation relies on said framework. - if (mExtTelephony == null) { + if (mExtTelephony == null || + !mContext.getResources().getBoolean(R.bool.config_enableManualSubProvisioning)) { mSwitch.setVisibility(View.GONE); } else { mSwitch.setVisibility(View.VISIBLE); - mSwitch.setEnabled(!isAirplaneModeOn()); + mSwitch.setEnabled(!isAirplaneModeOn() && isCurrentSubValid()); } } @@ -689,26 +691,44 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable if (!mSwitch.isEnabled()) { return; } - int result = -1; + new SimEnablerDisabler().execute(); + } + + private class SimEnablerDisabler extends AsyncTask<Void, Void, Integer> { + int newProvisionedState = NOT_PROVISIONED; - mCmdInProgress = true; - showProgressDialog(); - setEnabled(false); - try { - if (mIsChecked) { - result = mExtTelephony.activateUiccCard(mSir.getSimSlotIndex()); - newProvisionedState = PROVISIONED; - } else { - result = mExtTelephony.deactivateUiccCard(mSir.getSimSlotIndex()); + @Override + protected void onPreExecute() { + super.onPreExecute(); + mCmdInProgress = true; + showProgressDialog(); + setEnabled(false); + } + + @Override + protected Integer doInBackground(Void... params) { + int result = -1; + newProvisionedState = NOT_PROVISIONED; + try { + if (mIsChecked) { + result = mExtTelephony.activateUiccCard(mSir.getSimSlotIndex()); + newProvisionedState = PROVISIONED; + } else { + result = mExtTelephony.deactivateUiccCard(mSir.getSimSlotIndex()); + } + } catch (RemoteException ex) { + loge("Activate sub failed " + result + " phoneId " + mSir.getSimSlotIndex()); + } catch (NullPointerException ex) { + loge("Failed to activate sub Exception: " + ex); } - } catch (RemoteException ex) { - loge("Activate sub failed " + result + " phoneId " + mSir.getSimSlotIndex()); - } catch (NullPointerException ex) { - loge("Failed to activate sub Exception: " + ex); + return result; } - processSetUiccDone(result, newProvisionedState); + @Override + protected void onPostExecute(Integer result) { + processSetUiccDone(result.intValue(), newProvisionedState); + } } private void processSetUiccDone(int result, int newProvisionedState) { @@ -724,7 +744,6 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable dismissDialog(sAlertDialog); dismissDialog(sProgressDialog); AlertDialog.Builder builder = new AlertDialog.Builder(mContext) - .setIcon(android.R.drawable.ic_dialog_alert) .setTitle(title); switch(dialogId) { @@ -819,6 +838,7 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable .OnClickListener() { public void onClick(DialogInterface dialog, int which) { if (which == DialogInterface.BUTTON_POSITIVE) { + dismissDialog(sAlertDialog); sendUiccProvisioningRequest(); } else if (which == DialogInterface.BUTTON_NEGATIVE) { update(); diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java index 85d2700..a172766 100644 --- a/src/com/android/settings/users/UserSettings.java +++ b/src/com/android/settings/users/UserSettings.java @@ -45,6 +45,7 @@ import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; import android.provider.Settings; +import android.provider.Settings.Global; import android.provider.Settings.Secure; import android.util.Log; import android.util.SparseArray; @@ -229,6 +230,11 @@ public class UserSettings extends SettingsPreferenceFragment filter.addAction(Intent.ACTION_USER_INFO_CHANGED); context.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null, mHandler); + + if (Global.getInt(getContext().getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) { + getActivity().finish(); + return; + } } @Override diff --git a/src/com/android/settings/wifi/AdvancedWifiSettings.java b/src/com/android/settings/wifi/AdvancedWifiSettings.java index f764dd4..b933a28 100644 --- a/src/com/android/settings/wifi/AdvancedWifiSettings.java +++ b/src/com/android/settings/wifi/AdvancedWifiSettings.java @@ -60,7 +60,6 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment private static final String KEY_COUNTRY_CODE = "wifi_countrycode"; private static final String KEY_NOTIFY_OPEN_NETWORKS = "notify_open_networks"; private static final String KEY_SLEEP_POLICY = "sleep_policy"; - private static final String KEY_POOR_NETWORK_DETECTION = "wifi_poor_network_detection"; private static final String KEY_INSTALL_CREDENTIALS = "install_credentials"; private static final String KEY_WIFI_ASSISTANT = "wifi_assistant"; private static final String KEY_WIFI_DIRECT = "wifi_direct"; @@ -71,6 +70,9 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment private NetworkScoreManager mNetworkScoreManager; private AppListSwitchPreference mWifiAssistantPreference; + private Preference mWpsPushPref; + private Preference mWpsPinPref; + private IntentFilter mFilter; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override @@ -79,6 +81,11 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment if (action.equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION) || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { refreshWifiInfo(); + } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { + int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, + WifiManager.WIFI_STATE_UNKNOWN); + mWpsPushPref.setEnabled(WifiManager.WIFI_STATE_ENABLED == state); + mWpsPinPref.setEnabled(WifiManager.WIFI_STATE_ENABLED == state); } } }; @@ -101,6 +108,7 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment mFilter = new IntentFilter(); mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); mNetworkScoreManager = (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE); } @@ -126,19 +134,6 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1); notifyOpenNetworks.setEnabled(mWifiManager.isWifiEnabled()); - SwitchPreference poorNetworkDetection = - (SwitchPreference) findPreference(KEY_POOR_NETWORK_DETECTION); - if (poorNetworkDetection != null) { - if (Utils.isWifiOnly(getActivity())) { - getPreferenceScreen().removePreference(poorNetworkDetection); - } else { - poorNetworkDetection.setChecked(Settings.Global.getInt(getContentResolver(), - Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, - WifiManager.DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED ? - 1 : 0) == 1); - } - } - Intent intent = new Intent(Credentials.INSTALL_AS_USER_ACTION); intent.setClassName("com.android.certinstaller", "com.android.certinstaller.CertInstallerMain"); @@ -162,25 +157,28 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment Preference wifiDirectPref = findPreference(KEY_WIFI_DIRECT); wifiDirectPref.setIntent(wifiDirectIntent); + final int wifiState = mWifiManager.getWifiState(); // WpsDialog: Create the dialog like WifiSettings does. - Preference wpsPushPref = findPreference(KEY_WPS_PUSH); - wpsPushPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { + mWpsPushPref = findPreference(KEY_WPS_PUSH); + mWpsPushPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { public boolean onPreferenceClick(Preference arg0) { WpsFragment wpsFragment = new WpsFragment(WpsInfo.PBC); wpsFragment.show(getFragmentManager(), KEY_WPS_PUSH); return true; } }); + mWpsPushPref.setEnabled(WifiManager.WIFI_STATE_ENABLED == wifiState); // WpsDialog: Create the dialog like WifiSettings does. - Preference wpsPinPref = findPreference(KEY_WPS_PIN); - wpsPinPref.setOnPreferenceClickListener(new OnPreferenceClickListener(){ + mWpsPinPref = findPreference(KEY_WPS_PIN); + mWpsPinPref.setOnPreferenceClickListener(new OnPreferenceClickListener(){ public boolean onPreferenceClick(Preference arg0) { WpsFragment wpsFragment = new WpsFragment(WpsInfo.DISPLAY); wpsFragment.show(getFragmentManager(), KEY_WPS_PIN); return true; } }); + mWpsPinPref.setEnabled(WifiManager.WIFI_STATE_ENABLED == wifiState); ListPreference frequencyPref = (ListPreference) findPreference(KEY_FREQUENCY_BAND); @@ -277,10 +275,6 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment Global.putInt(getContentResolver(), Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, ((SwitchPreference) preference).isChecked() ? 1 : 0); - } else if (KEY_POOR_NETWORK_DETECTION.equals(key)) { - Global.putInt(getContentResolver(), - Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, - ((SwitchPreference) preference).isChecked() ? 1 : 0); } else { return super.onPreferenceTreeClick(screen, preference); } diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java index a3140a1..e7166da 100644 --- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java +++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java @@ -177,6 +177,8 @@ public class SavedAccessPointsWifiSettings extends RestrictedSettingsFragment if (savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) { mAccessPointSavedState = savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE); + mDlgAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState); + mSelectedAccessPoint = mDlgAccessPoint; } mPrioritiesOrderChanged = savedInstanceState.getBoolean( PRIORITIES_ORDER_CHANGED_STATE, false); @@ -270,8 +272,13 @@ public class SavedAccessPointsWifiSettings extends RestrictedSettingsFragment final int accessPointsSize = accessPoints.size(); for (int i = 0; i < accessPointsSize; ++i){ - AccessPointPreference preference = new AccessPointPreference(accessPoints.get(i), + AccessPoint accessPoint = accessPoints.get(i); + AccessPointPreference preference = new AccessPointPreference(accessPoint, context, mUserBadgeCache, true, true); + if (mSelectedAccessPoint != null && + mSelectedAccessPoint.getNetworkId() == accessPoint.getNetworkId()) { + mSelectedAccessPoint = accessPoint; + } preference.setOrder(i); preferenceScreen.addPreference(preference); } @@ -297,11 +304,6 @@ public class SavedAccessPointsWifiSettings extends RestrictedSettingsFragment public Dialog onCreateDialog(int dialogId) { switch (dialogId) { case WifiSettings.WIFI_DIALOG_ID: - if (mDlgAccessPoint == null) { // For re-launch from saved state - mDlgAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState); - // Reset the saved access point data - mAccessPointSavedState = null; - } mSelectedAccessPoint = mDlgAccessPoint; // Hide forget button if config editing is locked down diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java index e83889c..5fc70e5 100644 --- a/src/com/android/settings/wifi/WifiSettings.java +++ b/src/com/android/settings/wifi/WifiSettings.java @@ -666,6 +666,10 @@ public class WifiSettings extends RestrictedSettingsFragment for (AccessPoint accessPoint : accessPoints) { // Ignore access points that are out of range. if (accessPoint.getLevel() != -1) { + if (accessPoint.isSaved() && (!accessPoint.foundInScanResult) + && (accessPoint.getDetailedState() == null)) { + continue; + } hasAvailableAccessPoints = true; if (accessPoint.getTag() != null) { final Preference pref = (Preference) accessPoint.getTag(); |