Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4f9cb36 authored by Roman Birg's avatar Roman Birg Committed by LuK1337
Browse files

SystemUI: add Profiles tile

Change-Id: I1fe49d44d17060c47fb7d6cf3356ec06c8d9d690
parent 958e4d05
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright (c) 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="64dp"
    android:height="64dp"
    android:viewportWidth="24"
    android:viewportHeight="24">

    <path
        android:fillColor="#4DFFFFFF"
        android:pathData="M14.304,5.455l0.79-1.93c0.079-0.193-0.013-0.413-0.206-0.492c-0.193-0.079-0.413,0.013-0.492,0.206 l-0.818,2c-0.903-0.207-2.055-0.286-3.433-0.286v0.005h0V4.953c-0.18,0-0.355,0.002-0.527,0.005H9.615 C8.468,4.976,7.495,5.06,6.71,5.239l-0.819-2C5.812,3.046,5.592,2.954,5.399,3.033C5.206,3.112,5.114,3.332,5.193,3.525l0.79,1.93 C4.934,5.852,4.377,6.523,4.377,7.6v2.261v0.587v0.644c0,1.98,1.876,2.588,5.238,2.643v0.003h0.209 c0.105,0.001,0.212,0.002,0.32,0.002v-0.002h0v0.002c0.108,0,0.214-0.001,0.32-0.002h0.015c3.484-0.034,5.432-0.628,5.432-2.646 v-0.644V9.861V7.6C15.909,6.523,15.352,5.852,14.304,5.455Z M7.179,11.014c-0.953,0-1.725-0.772-1.725-1.724 c0-0.953,0.772-1.725,1.725-1.725c0.952,0,1.724,0.772,1.724,1.725C8.904,10.242,8.132,11.014,7.179,11.014z M10.325,12.265H9.961 c-0.268,0-0.485-0.217-0.485-0.485c0-0.01,0.002-0.019,0.003-0.029h1.328c0.001,0.01,0.003,0.019,0.003,0.029  C10.81,12.048,10.593,12.265,10.325,12.265z M13.107,11.014c-0.953,0-1.725-0.772-1.725-1.724c0-0.953,0.772-1.725,1.725-1.725 c0.952,0,1.724,0.772,1.724,1.725C14.832,10.242,14.06,11.014,13.107,11.014z M21.44,10.402c-0.261,1.016-0.5,4.301-5.798,7.557 c-0.439,0.269-0.884,0.974-0.884,2.152l0.05,0.89h-1.922v0h-0.014c0-1.492-1.214-2.706-2.706-2.706 c-1.492,0-2.706,1.214-2.706,2.706v0H5.525l0.07-1.243c0,0-0.203,0.516-0.489,1.243H2.501l1.563-4.171 c0.303-0.793,1.013-1.282,1.733-1.529c0.524-0.18,1.593-0.386,3.586-0.485h1.569c0.492,0.025,0.926,0.055,1.311,0.091 c0,0,0,0,0.001,0s0,0,0.001,0c0.296,0.027,0.563,0.057,0.801,0.089c1.028,0.062,2.506-0.095,4.131-1.475 c1.423-1.209,1.591-2.051,2.28-3.895C20.285,7.463,21.816,8.936,21.44,10.402z M12.316,21h0.013v0H8.02v0H8.019 c0-1.185,0.964-2.148,2.149-2.148C11.352,18.851,12.316,19.815,12.316,21z" />
</vector>
+26 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright (c) 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="64dp"
    android:height="64dp"
    android:viewportWidth="24"
    android:viewportHeight="24">

    <path
        android:fillColor="#FFFFFF"
        android:pathData="M14.304,5.455l0.79-1.93c0.079-0.193-0.013-0.413-0.206-0.492c-0.193-0.079-0.413,0.013-0.492,0.206 l-0.818,2c-0.903-0.207-2.055-0.286-3.433-0.286v0.005h0V4.953c-0.18,0-0.355,0.002-0.527,0.005H9.615 C8.468,4.976,7.495,5.06,6.71,5.239l-0.819-2C5.812,3.046,5.592,2.954,5.399,3.033C5.206,3.112,5.114,3.332,5.193,3.525l0.79,1.93 C4.934,5.852,4.377,6.523,4.377,7.6v2.261v0.587v0.644c0,1.98,1.876,2.588,5.238,2.643v0.003h0.209 c0.105,0.001,0.212,0.002,0.32,0.002v-0.002h0v0.002c0.108,0,0.214-0.001,0.32-0.002h0.015c3.484-0.034,5.432-0.628,5.432-2.646 v-0.644V9.861V7.6C15.909,6.523,15.352,5.852,14.304,5.455Z M7.179,11.014c-0.953,0-1.725-0.772-1.725-1.724 c0-0.953,0.772-1.725,1.725-1.725c0.952,0,1.724,0.772,1.724,1.725C8.904,10.242,8.132,11.014,7.179,11.014z M10.325,12.265H9.961 c-0.268,0-0.485-0.217-0.485-0.485c0-0.01,0.002-0.019,0.003-0.029h1.328c0.001,0.01,0.003,0.019,0.003,0.029  C10.81,12.048,10.593,12.265,10.325,12.265z M13.107,11.014c-0.953,0-1.725-0.772-1.725-1.724c0-0.953,0.772-1.725,1.725-1.725 c0.952,0,1.724,0.772,1.724,1.725C14.832,10.242,14.06,11.014,13.107,11.014z M21.44,10.402c-0.261,1.016-0.5,4.301-5.798,7.557 c-0.439,0.269-0.884,0.974-0.884,2.152l0.05,0.89h-1.922v0h-0.014c0-1.492-1.214-2.706-2.706-2.706 c-1.492,0-2.706,1.214-2.706,2.706v0H5.525l0.07-1.243c0,0-0.203,0.516-0.489,1.243H2.501l1.563-4.171 c0.303-0.793,1.013-1.282,1.733-1.529c0.524-0.18,1.593-0.386,3.586-0.485h1.569c0.492,0.025,0.926,0.055,1.311,0.091 c0,0,0,0,0.001,0s0,0,0.001,0c0.296,0.027,0.563,0.057,0.801,0.089c1.028,0.062,2.506-0.095,4.131-1.475 c1.423-1.209,1.591-2.051,2.28-3.895C20.285,7.463,21.816,8.936,21.44,10.402z M12.316,21h0.013v0H8.02v0H8.019 c0-1.185,0.964-2.148,2.149-2.148C11.352,18.851,12.316,19.815,12.316,21z" />
</vector>
+31 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 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.
-->
<com.android.systemui.qs.tiles.ProfilesDetailView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        android:orientation="vertical">

    <ListView
            android:id="@android:id/list"
            android:divider="@null"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

</com.android.systemui.qs.tiles.ProfilesDetailView>
+13 −0
Original line number Diff line number Diff line
@@ -68,6 +68,17 @@

    <!-- Content description of the light brightness slider (not shown on the screen). [CHAR LIMIT=NONE] -->
    <string name="accessibility_notification_brightness">Light brightness</string>

    <!-- Content description of the profiles tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
    <string name="accessibility_quick_settings_profiles_off">Profiles off.</string>
    <!-- Content description of the profiles tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
    <string name="accessibility_quick_settings_profiles">Profile: <xliff:g id="profile" example="Default">%s</xliff:g>.</string>

    <!-- Announcement made when the profiles tile changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
    <string name="accessibility_quick_settings_profiles_changed_off">Profiles turned off.</string>
    <!-- Announcement made when the profiles tile changes (not shown on the screen). [CHAR LIMIT=NONE] -->
    <string name="accessibility_quick_settings_profiles_changed">Profile changed to <xliff:g id="profile" example="Default">%s</xliff:g>.</string>

    <string name="quick_settings_compass_value" translatable="false"><xliff:g id="degrees">%1$.0f</xliff:g>\u00b0 <xliff:g id="direction">%2$s</xliff:g></string>
    <string name="quick_settings_compass_off">Compass off</string>
    <string name="quick_settings_compass_init">Initializing\u2026</string>
@@ -97,6 +108,8 @@
    <string name="qs_tile_compass">Compass</string>
    <string name="quick_settings_nfc">NFC</string>
    <string name="quick_settings_nfc_off">NFC off</string>
    <string name="quick_settings_profiles">System profiles</string>
    <string name="quick_settings_profiles_off">Profiles disabled</string>

    <!-- Content description of the sync tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
    <string name="accessibility_quick_settings_sync_off">Sync off.</string>
+269 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 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.systemui.qs.tiles;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.media.AudioManager;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.ListView;

import com.android.internal.logging.MetricsConstants;
import com.android.systemui.R;
import com.android.systemui.qs.QSDetailItemsList;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.KeyguardMonitor;

import cyanogenmod.app.Profile;
import cyanogenmod.app.ProfileManager;
import cyanogenmod.app.StatusBarPanelCustomTile;
import cyanogenmod.providers.CMSettings;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class ProfilesTile extends QSTile<QSTile.State> {

    private static final Intent PROFILES_SETTINGS =
            new Intent("android.settings.PROFILES_SETTINGS");

    private boolean mListening;
    private ProfilesObserver mObserver;
    private ProfileManager mProfileManager;
    private QSDetailItemsList mDetails;
    private ProfileAdapter mAdapter;

    public ProfilesTile(Host host) {
        super(host);
        mProfileManager = ProfileManager.getInstance(mContext);
        mObserver = new ProfilesObserver(mHandler);
    }

    @Override
    protected State newTileState() {
        return new State();
    }

    @Override
    protected void handleClick() {
        showDetail(true);
    }

    @Override
    protected void handleLongClick() {
        mHost.startActivityDismissingKeyguard(PROFILES_SETTINGS);
    }

    @Override
    protected void handleUpdateState(State state, Object arg) {
        state.visible = true;
        if (profilesEnabled()) {
            state.icon = ResourceIcon.get(R.drawable.ic_qs_profiles_on);
            state.label = mProfileManager.getActiveProfile().getName();
            state.contentDescription = mContext.getString(
                    R.string.accessibility_quick_settings_profiles, state.label);
        } else {
            state.icon = ResourceIcon.get(R.drawable.ic_qs_profiles_off);
            state.label = mContext.getString(R.string.quick_settings_profiles_off);
            state.contentDescription = mContext.getString(
                    R.string.accessibility_quick_settings_profiles_off);
        }
    }

    @Override
    protected String composeChangeAnnouncement() {
        if (profilesEnabled()) {
            return mContext.getString(R.string.accessibility_quick_settings_profiles_changed,
                    mState.label);
        } else {
            return mContext.getString(R.string.accessibility_quick_settings_profiles_changed_off);
        }
    }

    private boolean profilesEnabled() {
        return CMSettings.System.getInt(mContext.getContentResolver(),
                CMSettings.System.SYSTEM_PROFILES_ENABLED, 1) == 1;
    }

    @Override
    public int getMetricsCategory() {
        return MetricsConstants.DONT_TRACK_ME_BRO;
    }

    @Override
    public void setListening(boolean listening) {
        if (mListening == listening) return;
        mListening = listening;
        if (listening) {
            mObserver.startObserving();
            final IntentFilter filter = new IntentFilter();
            filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_SELECTED);
            filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_UPDATED);
            mContext.registerReceiver(mReceiver, filter);
        } else {
            mObserver.endObserving();
            mContext.unregisterReceiver(mReceiver);
        }
    }

    @Override
    public DetailAdapter getDetailAdapter() {
        return new ProfileDetailAdapter();
    }

    private class ProfileAdapter extends ArrayAdapter<Profile> {
        public ProfileAdapter(Context context, List<Profile> profiles) {
            super(context, android.R.layout.simple_list_item_single_choice, profiles);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            CheckedTextView label = (CheckedTextView) inflater.inflate(
                    android.R.layout.simple_list_item_single_choice, parent, false);

            Profile p = getItem(position);
            label.setText(p.getName());

            return label;
        }
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (ProfileManager.INTENT_ACTION_PROFILE_SELECTED.equals(intent.getAction())
                    || ProfileManager.INTENT_ACTION_PROFILE_UPDATED.equals(intent.getAction())) {
                refreshState();
            }
        }
    };

    public class ProfileDetailAdapter implements DetailAdapter, AdapterView.OnItemClickListener {

        private List<Profile> mProfilesList;

        @Override
        public int getTitle() {
            return R.string.quick_settings_profiles;
        }

        @Override
        public Boolean getToggleState() {
            boolean enabled = profilesEnabled();
            rebuildProfilesList(enabled);
            return enabled;
        }

        @Override
        public int getMetricsCategory() {
            return MetricsConstants.DONT_TRACK_ME_BRO;
        }

        @Override
        public View createDetailView(Context context, View convertView, ViewGroup parent) {
            mDetails = QSDetailItemsList.convertOrInflate(context, convertView, parent);
            mProfilesList = new ArrayList<>();
            mDetails.setAdapter(mAdapter = new ProfileAdapter(context, mProfilesList));

            final ListView list = mDetails.getListView();
            list.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
            list.setOnItemClickListener(this);

            mDetails.setEmptyState(R.drawable.ic_qs_profiles_off,
                    R.string.quick_settings_profiles_off);

            return mDetails;
        }

        private void rebuildProfilesList(boolean populate) {
            mProfilesList.clear();
            if (populate) {
                int selected = -1;

                final Profile[] profiles = mProfileManager.getProfiles();
                final Profile activeProfile = mProfileManager.getActiveProfile();
                final UUID activeUuid = activeProfile != null ? activeProfile.getUuid() : null;

                for (int i = 0; i < profiles.length; i++) {
                    mProfilesList.add(profiles[i]);
                    if (activeUuid != null && activeUuid.equals(profiles[i].getUuid())) {
                        selected = i;
                    }
                }
                mDetails.getListView().setItemChecked(selected, true);
            }
            mAdapter.notifyDataSetChanged();
        }

        @Override
        public Intent getSettingsIntent() {
            return PROFILES_SETTINGS;
        }

        @Override
        public StatusBarPanelCustomTile getCustomTile() {
            return null;
        }

        @Override
        public void setToggleState(boolean state) {
            CMSettings.System.putInt(mContext.getContentResolver(),
                    CMSettings.System.SYSTEM_PROFILES_ENABLED, state ? 1 : 0);
            fireToggleStateChanged(state);
            rebuildProfilesList(state);
        }

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Profile selected = (Profile) parent.getItemAtPosition(position);
            mProfileManager.setActiveProfile(selected.getUuid());
        }
    }

    private class ProfilesObserver extends ContentObserver {
        public ProfilesObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            refreshState();
        }

        public void startObserving() {
            mContext.getContentResolver().registerContentObserver(
                    CMSettings.System.getUriFor(CMSettings.System.SYSTEM_PROFILES_ENABLED),
                    false, this);
        }

        public void endObserving() {
            mContext.getContentResolver().unregisterContentObserver(this);
        }
    }
}
Loading