diff options
author | d34d <clark@cyngn.com> | 2016-01-22 14:27:22 -0800 |
---|---|---|
committer | d34d <clark@cyngn.com> | 2016-02-02 09:52:02 -0800 |
commit | eb2af24814224344204e9c423fcfb94ff67d25f8 (patch) | |
tree | a17de4d12ea3c9d9462a6879da94e7cd62dc091b /src/com/android/settings/cyanogenmod | |
parent | d8ed0a392ac62a99a2daf1b55014578ac9631194 (diff) | |
download | packages_apps_Settings-eb2af24814224344204e9c423fcfb94ff67d25f8.zip packages_apps_Settings-eb2af24814224344204e9c423fcfb94ff67d25f8.tar.gz packages_apps_Settings-eb2af24814224344204e9c423fcfb94ff67d25f8.tar.bz2 |
LiveLockScreen: Add live lock screen settings
This will allow the user to enable and configure their installed
live lock screens.
Change-Id: Id4a6963cc49d1c361c99c95b17a961aaa980ed48
TICKET: CYNGNOS-1686
Diffstat (limited to 'src/com/android/settings/cyanogenmod')
-rw-r--r-- | src/com/android/settings/cyanogenmod/LiveLockScreenSettings.java | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/src/com/android/settings/cyanogenmod/LiveLockScreenSettings.java b/src/com/android/settings/cyanogenmod/LiveLockScreenSettings.java new file mode 100644 index 0000000..4ffcc31 --- /dev/null +++ b/src/com/android/settings/cyanogenmod/LiveLockScreenSettings.java @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * 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.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Xml; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnTouchListener; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.RadioButton; +import android.widget.Switch; +import android.widget.TextView; +import com.android.internal.logging.MetricsLogger; +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.Utils; +import com.android.settings.widget.SwitchBar; +import cyanogenmod.externalviews.KeyguardExternalViewProviderService; +import cyanogenmod.providers.CMSettings; +import org.cyanogenmod.internal.util.CmLockPatternUtils; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static cyanogenmod.providers.CMSettings.Secure.LIVE_LOCK_SCREEN_ENABLED; + +public class LiveLockScreenSettings extends SettingsPreferenceFragment implements + SwitchBar.OnSwitchChangeListener { + private static final String TAG = LiveLockScreenSettings.class.getSimpleName(); + static final boolean DEBUG = false; + private static final String PACKAGE_SCHEME = "package"; + + private final PackageReceiver mPackageReceiver = new PackageReceiver(); + + private Context mContext; + private LiveLockScreenBackend mBackend; + private LiveLockScreenInfoAdapter mAdapter; + private SwitchBar mSwitchBar; + private boolean mRefreshing; + + @Override + public void onAttach(Activity activity) { + logd("onAttach(%s)", activity.getClass().getSimpleName()); + super.onAttach(activity); + mContext = activity; + } + + @Override + protected int getMetricsCategory() { + return MetricsLogger.LOCKSCREEN; + } + + @Override + public void onCreate(Bundle icicle) { + logd("onCreate(%s)", icicle); + super.onCreate(icicle); + + mBackend = new LiveLockScreenBackend(getActivity()); + } + + @Override + public void onSwitchChanged(Switch switchView, boolean isChecked) { + if (!mRefreshing) { + mBackend.setEnabled(isChecked); + refreshFromBackend(); + } + } + + @Override + public void onStart() { + logd("onStart()"); + super.onStart(); + } + + @Override + public void onDestroyView() { + logd("onDestroyView()"); + super.onDestroyView(); + + mSwitchBar.removeOnSwitchChangeListener(this); + mSwitchBar.hide(); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + logd("onActivityCreated(%s)", savedInstanceState); + super.onActivityCreated(savedInstanceState); + + ListView listView = getListView(); + listView.setItemsCanFocus(true); + + TextView emptyView = (TextView) getView().findViewById(android.R.id.empty); + emptyView.setText(R.string.live_lock_screen_settings_disabled_prompt); + listView.setEmptyView(emptyView); + + mAdapter = new LiveLockScreenInfoAdapter(mContext); + listView.setAdapter(mAdapter); + + final SettingsActivity sa = (SettingsActivity) getActivity(); + mSwitchBar = sa.getSwitchBar(); + mSwitchBar.addOnSwitchChangeListener(this); + mSwitchBar.show(); + } + + @Override + public void onPause() { + logd("onPause()"); + super.onPause(); + + mContext.unregisterReceiver(mPackageReceiver); + } + + @Override + public void onResume() { + logd("onResume()"); + super.onResume(); + refreshFromBackend(); + + // listen for package changes + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addAction(Intent.ACTION_PACKAGE_REPLACED); + filter.addDataScheme(PACKAGE_SCHEME); + mContext.registerReceiver(mPackageReceiver , filter); + } + + private void refreshFromBackend() { + logd("refreshFromBackend()"); + mRefreshing = true; + boolean liveLockScreenEnabled = mBackend.isEnabled(); + if (mSwitchBar.isChecked() != liveLockScreenEnabled) { + mSwitchBar.setChecked(liveLockScreenEnabled); + } + + mAdapter.clear(); + if (liveLockScreenEnabled) { + List<LiveLockScreenBackend.LiveLockScreenInfo> liveLockScreenInfos = + mBackend.getLiveLockScreenInfos(); + mAdapter.addAll(liveLockScreenInfos); + } + mRefreshing = false; + } + + private static void logd(String msg, Object... args) { + if (DEBUG) { + Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args)); + } + } + + private class LiveLockScreenInfoAdapter extends ArrayAdapter<LiveLockScreenBackend.LiveLockScreenInfo> { + private final LayoutInflater mInflater; + + public LiveLockScreenInfoAdapter(Context context) { + super(context, 0); + mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LiveLockScreenBackend.LiveLockScreenInfo liveLockScreenInfo = getItem(position); + logd("getView(%s)", liveLockScreenInfo.caption); + final View row = convertView != null ? convertView : + createLiveLockScreenInfoRow(parent); + row.setTag(liveLockScreenInfo); + + // bind icon + ((ImageView) row.findViewById(android.R.id.icon)) + .setImageDrawable(liveLockScreenInfo.icon); + + // bind caption + ((TextView) row.findViewById(android.R.id.title)).setText(liveLockScreenInfo.caption); + + // bind radio button + RadioButton radioButton = (RadioButton) row.findViewById(android.R.id.button1); + radioButton.setChecked(liveLockScreenInfo.isActive); + radioButton.setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + row.onTouchEvent(event); + return false; + }}); + + // bind settings button + divider + boolean showSettings = liveLockScreenInfo.settingsComponentName != null; + View settingsDivider = row.findViewById(R.id.divider); + settingsDivider.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); + + ImageView settingsButton = (ImageView) row.findViewById(android.R.id.button2); + settingsButton.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); + settingsButton.setAlpha(liveLockScreenInfo.isActive ? 1f : Utils.DISABLED_ALPHA); + settingsButton.setEnabled(liveLockScreenInfo.isActive); + settingsButton.setFocusable(liveLockScreenInfo.isActive); + settingsButton.setOnClickListener(new OnClickListener(){ + @Override + public void onClick(View v) { + mBackend.launchSettings( + (LiveLockScreenBackend.LiveLockScreenInfo) row.getTag()); + }}); + + return row; + } + + 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(){ + @Override + public void onClick(View v) { + v.setPressed(true); + activate((LiveLockScreenBackend.LiveLockScreenInfo) row.getTag()); + }}); + return row; + } + + private LiveLockScreenBackend.LiveLockScreenInfo getCurrentSelection() { + for (int i = 0; i < getCount(); i++) { + LiveLockScreenBackend.LiveLockScreenInfo liveLockScreenInfo = getItem(i); + if (liveLockScreenInfo.isActive) { + return liveLockScreenInfo; + } + } + return null; + } + private void activate(LiveLockScreenBackend.LiveLockScreenInfo liveLockScreenInfo) { + if (liveLockScreenInfo.equals(getCurrentSelection())) { + return; + } + for (int i = 0; i < getCount(); i++) { + getItem(i).isActive = false; + } + liveLockScreenInfo.isActive = true; + mBackend.setActiveLiveLockScreen(liveLockScreenInfo.componentName); + if (liveLockScreenInfo.settingsComponentName != null) { + mBackend.launchSettings(liveLockScreenInfo); + } + notifyDataSetChanged(); + } + } + + private class PackageReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + logd("PackageReceiver.onReceive"); + refreshFromBackend(); + } + } + + public static class LiveLockScreenBackend { + private static final String TAG = LiveLockScreenSettings.class.getSimpleName() + ".Backend"; + + public static class LiveLockScreenInfo { + CharSequence caption; + Drawable icon; + boolean isActive; + public ComponentName componentName; + public ComponentName settingsComponentName; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(LiveLockScreenInfo.class.getSimpleName()); + sb.append('[').append(caption); + if (isActive) { + sb.append(",active"); + } + sb.append(',').append(componentName); + if (settingsComponentName != null) { + sb.append("settings=").append(settingsComponentName); + } + return sb.append(']').toString(); + } + } + + private final Context mContext; + private final LiveLockScreenInfoComparator mComparator; + private CmLockPatternUtils mLockPatternUtils; + + public LiveLockScreenBackend(Context context) { + mContext = context; + mComparator = new LiveLockScreenInfoComparator(null); + mLockPatternUtils = new CmLockPatternUtils(context); + } + + public List<LiveLockScreenInfo> getLiveLockScreenInfos() { + logd("getLiveLockScreenInfos()"); + ComponentName activeLiveLockScreen = getActiveLiveLockScreen(); + PackageManager pm = mContext.getPackageManager(); + Intent liveLockScreenIntent = + new Intent(KeyguardExternalViewProviderService.SERVICE_INTERFACE); + List<ResolveInfo> resolveInfos = pm.queryIntentServices(liveLockScreenIntent, + PackageManager.GET_META_DATA); + List<LiveLockScreenInfo> liveLockScreenInfos = new ArrayList<>(resolveInfos.size()); + for (ResolveInfo resolveInfo : resolveInfos) { + if (resolveInfo.serviceInfo == null) { + continue; + } + LiveLockScreenInfo liveLockScreenInfo = new LiveLockScreenInfo(); + liveLockScreenInfo.caption = resolveInfo.loadLabel(pm); + liveLockScreenInfo.icon = resolveInfo.loadIcon(pm); + liveLockScreenInfo.componentName = getLiveLockScreenComponentName(resolveInfo); + liveLockScreenInfo.isActive = liveLockScreenInfo.componentName.equals( + activeLiveLockScreen); + liveLockScreenInfo.settingsComponentName = + getSettingsComponentName(pm, resolveInfo); + liveLockScreenInfos.add(liveLockScreenInfo); + } + Collections.sort(liveLockScreenInfos, mComparator); + return liveLockScreenInfos; + } + + public CharSequence getActiveLiveLockScreenName() { + ComponentName cn = getActiveLiveLockScreen(); + if (cn != null) { + PackageManager pm = mContext.getPackageManager(); + try { + ServiceInfo ri = pm.getServiceInfo(cn, 0); + if (ri != null) { + return ri.loadLabel(pm); + } + } catch (PackageManager.NameNotFoundException exc) { + return null; // uninstalled? + } + } + return null; + } + + public boolean isEnabled() { + return getBoolean(LIVE_LOCK_SCREEN_ENABLED, false); + } + + public void setEnabled(boolean value) { + logd("setEnabled(%s)", value); + setBoolean(LIVE_LOCK_SCREEN_ENABLED, value); + } + + private boolean getBoolean(String key, boolean def) { + return CMSettings.Secure.getInt(mContext.getContentResolver(), key, def ? 1 : 0) == 1; + } + + private void setBoolean(String key, boolean value) { + CMSettings.Secure.putInt(mContext.getContentResolver(), key, value ? 1 : 0); + } + + 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); + } + } + + public ComponentName getActiveLiveLockScreen() { + if (mLockPatternUtils == null) { + return null; + } + return mLockPatternUtils.getThirdPartyKeyguardComponent(); + } + + public void launchSettings(LiveLockScreenInfo liveLockScreenInfo) { + logd("launchSettings(%s)", liveLockScreenInfo); + if (liveLockScreenInfo == null || liveLockScreenInfo.settingsComponentName == null) { + return; + } + mContext.startActivity(new Intent().setComponent( + liveLockScreenInfo.settingsComponentName)); + } + + private static ComponentName getLiveLockScreenComponentName(ResolveInfo resolveInfo) { + if (resolveInfo == null || resolveInfo.serviceInfo == null) { + return null; + } + return new ComponentName(resolveInfo.serviceInfo.packageName, + resolveInfo.serviceInfo.name); + } + + private static ComponentName getSettingsComponentName(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, + KeyguardExternalViewProviderService.META_DATA); + if (parser == null) { + Log.w(TAG, "No " + KeyguardExternalViewProviderService.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 (!"lockscreen".equals(nodeName)) { + Log.w(TAG, "Meta-data does not start with lockscreen tag"); + return null; + } + // Dream styleable has the attributes we need so we'll piggy back off of that + 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 static void logd(String msg, Object... args) { + if (LiveLockScreenSettings.DEBUG) { + Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args)); + } + } + + private static class LiveLockScreenInfoComparator implements + Comparator<LiveLockScreenInfo> { + private final ComponentName mDefaultLiveLockScreen; + + public LiveLockScreenInfoComparator(ComponentName defaultLiveLockScreen) { + mDefaultLiveLockScreen = defaultLiveLockScreen; + } + + @Override + public int compare(LiveLockScreenInfo lhs, LiveLockScreenInfo rhs) { + return sortKey(lhs).compareTo(sortKey(rhs)); + } + + private String sortKey(LiveLockScreenInfo di) { + StringBuilder sb = new StringBuilder(); + sb.append(di.componentName.equals(mDefaultLiveLockScreen) ? '0' : '1'); + sb.append(di.caption); + return sb.toString(); + } + } + } +} |