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

Commit a5288771 authored by Danny Baumann's avatar Danny Baumann Committed by Ricardo Cerqueira
Browse files

Allow theming of framework UI elements.

As the theme engine works by replacing resources while loading the APK,
framework UI couldn't be themed so far. Workaround that by manually
creating a com.android.systemui package context and using that for
showing the UI. This attempt is a bit hacky, but should be safe as
a) systemui should always be present
b) if it isn't, we fall back to no theming

Change-Id: I644e2e8d7d4abf07bae639b606197d691f16adac

Applying theming to more framework items.

All dialogs and notifications should be covered now.

Change-Id: If93f81991361165a00b5b1b03ffc323e3ab42c0b
parent 818c3be9
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3886,7 +3886,7 @@ public final class ActivityThread {
                // We removed the old resources object from the mActiveResources
                // cache, now we need to trigger an update for each application.
                if ((diff & ActivityInfo.CONFIG_THEME_RESOURCE) != 0) {
                    if (cb instanceof Activity || cb instanceof Application) {
                    if (cb instanceof ContextWrapper) {
                        Context context = ((ContextWrapper)cb).getBaseContext();
                        if (context instanceof ContextImpl) {
                            ((ContextImpl)context).refreshResourcesIfNecessary();
+18 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.content;

import com.android.internal.R;
import com.android.internal.app.ThemeUtils;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;

@@ -136,6 +137,7 @@ public class SyncManager implements OnAccountsUpdateListener {
    private static final int MAX_SIMULTANEOUS_INITIALIZATION_SYNCS;

    private Context mContext;
    private Context mUiContext;

    private static final AccountAndUser[] INITIAL_ACCOUNTS_ARRAY = new AccountAndUser[0];

@@ -191,6 +193,12 @@ public class SyncManager implements OnAccountsUpdateListener {
        }
    };

    private BroadcastReceiver mThemeChangeReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            mUiContext = null;
        }
    };

    private BroadcastReceiver mBackgroundDataSettingChanged = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            if (getConnectivityManager().getBackgroundDataSetting()) {
@@ -398,6 +406,8 @@ public class SyncManager implements OnAccountsUpdateListener {
        intentFilter.addAction(Intent.ACTION_USER_REMOVED);
        mContext.registerReceiver(mUserIntentReceiver, intentFilter);

        ThemeUtils.registerThemeChangeReceiver(mContext, mThemeChangeReceiver);

        if (!factoryTest) {
            mNotificationMgr = (NotificationManager)
                context.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -901,6 +911,13 @@ public class SyncManager implements OnAccountsUpdateListener {
        }
    }

    private Context getUiContext() {
        if (mUiContext == null) {
            mUiContext = ThemeUtils.createUiContext(mContext);
        }
        return mUiContext != null ? mUiContext : mContext;
    }

    /**
     * @hide
     */
@@ -2497,7 +2514,7 @@ public class SyncManager implements OnAccountsUpdateListener {
                new Notification(R.drawable.stat_notify_sync_error,
                        mContext.getString(R.string.contentServiceSync),
                        System.currentTimeMillis());
            notification.setLatestEventInfo(mContext,
            notification.setLatestEventInfo(getUiContext(),
                    mContext.getString(R.string.contentServiceSyncNotificationTitle),
                    String.format(tooManyDeletesDescFormat.toString(), authorityName),
                    pendingIntent);
+56 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 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.internal.app;

import android.content.Context;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.util.Log;

/**
 * @hide
 */

public class ThemeUtils {
    private static final String TAG = "ThemeUtils";
    private static final String DATA_TYPE_TMOBILE_STYLE = "vnd.tmobile.cursor.item/style";
    private static final String DATA_TYPE_TMOBILE_THEME = "vnd.tmobile.cursor.item/theme";
    private static final String ACTION_TMOBILE_THEME_CHANGED = "com.tmobile.intent.action.THEME_CHANGED";

    public static Context createUiContext(final Context context) {
        try {
            return context.createPackageContext("com.android.systemui", Context.CONTEXT_RESTRICTED);
        } catch (PackageManager.NameNotFoundException e) {
        }

        return null;
    }

    public static void registerThemeChangeReceiver(final Context context, final BroadcastReceiver receiver) {
        IntentFilter filter = new IntentFilter(ACTION_TMOBILE_THEME_CHANGED);
        try {
            filter.addDataType(DATA_TYPE_TMOBILE_THEME);
            filter.addDataType(DATA_TYPE_TMOBILE_STYLE);
        } catch (IntentFilter.MalformedMimeTypeException e) {
            Log.e(TAG, "Could not add MIME types to filter", e);
        }

        context.registerReceiver(receiver, filter);
    }
}
+31 −3
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ import android.view.KeyEvent;
import android.view.VolumePanel;
import android.provider.Settings.SettingNotFoundException;

import com.android.internal.app.ThemeUtils;
import com.android.internal.telephony.ITelephony;

import java.io.FileDescriptor;
@@ -114,6 +115,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {

    /** The UI */
    private VolumePanel mVolumePanel;
    private Context mUiContext;
    private Handler mHandler;

    // sendMsg() flags
    /** If the msg is already queued, replace it with this one. */
@@ -448,6 +451,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
    public AudioService(Context context) {
        mContext = context;
        mContentResolver = context.getContentResolver();
        mHandler = new Handler();
        mVoiceCapable = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_voice_capable);

@@ -465,7 +469,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        SOUND_EFFECT_VOLUME_DB = context.getResources().getInteger(
                com.android.internal.R.integer.config_soundEffectVolumeDb);

        mVolumePanel = new VolumePanel(context, this);
        mMode = AudioSystem.MODE_NORMAL;
        mForcedUseForComm = AudioSystem.FORCE_NONE;
        createAudioSystemThread();
@@ -512,6 +515,13 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        pkgFilter.addDataScheme("package");
        context.registerReceiver(mReceiver, pkgFilter);

        ThemeUtils.registerThemeChangeReceiver(context, new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                mUiContext = null;
            }
        });

        // Register for phone state monitoring
        TelephonyManager tmgr = (TelephonyManager)
                context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -972,8 +982,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            streamType = AudioSystem.STREAM_NOTIFICATION;
        }

        mVolumePanel.postVolumeChanged(streamType, flags);

        showVolumeChangeUi(streamType, flags);
        oldIndex = (oldIndex + 5) / 10;
        index = (index + 5) / 10;
        Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
@@ -3665,6 +3674,25 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        }
    }

    private void showVolumeChangeUi(final int streamType, final int flags) {
        if (mUiContext != null && mVolumePanel != null) {
            mVolumePanel.postVolumeChanged(streamType, flags);
        } else {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mUiContext == null) {
                        mUiContext = ThemeUtils.createUiContext(mContext);
                    }

                    final Context context = mUiContext != null ? mUiContext : mContext;
                    mVolumePanel = new VolumePanel(context, AudioService.this);
                    mVolumePanel.postVolumeChanged(streamType, flags);
                }
            });
        }
    }

    //==========================================================================================
    // AudioFocus
    //==========================================================================================
+23 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.policy.impl;

import com.android.internal.R;
import com.android.internal.app.ThemeUtils;
import com.android.internal.widget.LockPatternUtils;

import android.accounts.Account;
@@ -25,6 +26,7 @@ import android.accounts.OperationCanceledException;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.AccountManagerCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -74,9 +76,18 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
    /**
     * Shown while making asynchronous check of password.
     */
    private Context mUiContext;
    private ProgressDialog mCheckingDialog;
    private KeyguardStatusViewManager mKeyguardStatusViewManager;

    private BroadcastReceiver mThemeChangeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            mUiContext = null;
            mCheckingDialog = null;
        }
    };

    /**
     * AccountUnlockScreen constructor.
     * @param configuration
@@ -139,6 +150,7 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree

    /** {@inheritDoc} */
    public void onPause() {
        mContext.unregisterReceiver(mThemeChangeReceiver);
        mKeyguardStatusViewManager.onPause();
    }

@@ -148,6 +160,7 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
        mLogin.setText("");
        mPassword.setText("");
        mLogin.requestFocus();
        ThemeUtils.registerThemeChangeReceiver(mContext, mThemeChangeReceiver);
        mKeyguardStatusViewManager.onResume();
    }

@@ -303,8 +316,17 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
    }

    private Dialog getProgressDialog() {
        if (mUiContext == null && mCheckingDialog != null) {
            mCheckingDialog.dismiss();
            mCheckingDialog = null;
        }

        if (mCheckingDialog == null) {
            mCheckingDialog = new ProgressDialog(mContext);
            mUiContext = ThemeUtils.createUiContext(mContext);

            final Context context = mUiContext != null ? mUiContext : mContext;

            mCheckingDialog = new ProgressDialog(context);
            mCheckingDialog.setMessage(
                    mContext.getString(R.string.lockscreen_glogin_checking_password));
            mCheckingDialog.setIndeterminate(true);
Loading