1 package com.android.launcher3.util; 2 3 /** 4 * Copyright (C) 2015 The Android Open Source Project 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; 20 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.content.res.Configuration; 26 import android.graphics.Point; 27 import android.util.Log; 28 29 import java.util.function.Consumer; 30 31 /** 32 * {@link BroadcastReceiver} which watches configuration changes and 33 * notifies the callback in case changes which affect the device profile occur. 34 */ 35 public class ConfigMonitor extends BroadcastReceiver implements 36 DefaultDisplay.DisplayInfoChangeListener { 37 38 private static final String TAG = "ConfigMonitor"; 39 40 private final Point mTmpPoint1 = new Point(); 41 private final Point mTmpPoint2 = new Point(); 42 43 private final Context mContext; 44 private final float mFontScale; 45 private final int mDensity; 46 47 private final int mDisplayId; 48 private final Point mRealSize; 49 private final Point mSmallestSize, mLargestSize; 50 51 private Consumer<Context> mCallback; 52 ConfigMonitor(Context context, Consumer<Context> callback)53 public ConfigMonitor(Context context, Consumer<Context> callback) { 54 mContext = context; 55 56 Configuration config = context.getResources().getConfiguration(); 57 mFontScale = config.fontScale; 58 mDensity = config.densityDpi; 59 60 DefaultDisplay display = DefaultDisplay.INSTANCE.get(context); 61 display.addChangeListener(this); 62 DefaultDisplay.Info displayInfo = display.getInfo(); 63 mDisplayId = displayInfo.id; 64 65 mRealSize = new Point(displayInfo.realSize); 66 mSmallestSize = new Point(displayInfo.smallestSize); 67 mLargestSize = new Point(displayInfo.largestSize); 68 69 mCallback = callback; 70 71 // Listen for configuration change 72 mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)); 73 } 74 75 @Override onReceive(Context context, Intent intent)76 public void onReceive(Context context, Intent intent) { 77 Configuration config = context.getResources().getConfiguration(); 78 if (mFontScale != config.fontScale || mDensity != config.densityDpi) { 79 Log.d(TAG, "Configuration changed."); 80 notifyChange(); 81 } 82 } 83 84 @Override onDisplayInfoChanged(DefaultDisplay.Info info, int flags)85 public void onDisplayInfoChanged(DefaultDisplay.Info info, int flags) { 86 if (info.id != mDisplayId) { 87 return; 88 } 89 mTmpPoint1.set(info.realSize.x, info.realSize.y); 90 if (!mRealSize.equals(mTmpPoint1) && !mRealSize.equals(mTmpPoint1.y, mTmpPoint1.x)) { 91 Log.d(TAG, String.format("Display size changed from %s to %s", mRealSize, mTmpPoint1)); 92 notifyChange(); 93 return; 94 } 95 96 mTmpPoint1.set(info.smallestSize.x, info.smallestSize.y); 97 mTmpPoint2.set(info.largestSize.x, info.largestSize.y); 98 if (!mSmallestSize.equals(mTmpPoint1) || !mLargestSize.equals(mTmpPoint2)) { 99 Log.d(TAG, String.format("Available size changed from [%s, %s] to [%s, %s]", 100 mSmallestSize, mLargestSize, mTmpPoint1, mTmpPoint2)); 101 notifyChange(); 102 } 103 } 104 notifyChange()105 private synchronized void notifyChange() { 106 if (mCallback != null) { 107 Consumer<Context> callback = mCallback; 108 mCallback = null; 109 MAIN_EXECUTOR.execute(() -> callback.accept(mContext)); 110 } 111 } 112 unregister()113 public void unregister() { 114 try { 115 mContext.unregisterReceiver(this); 116 DefaultDisplay display = DefaultDisplay.INSTANCE.get(mContext); 117 display.removeChangeListener(this); 118 } catch (Exception e) { 119 Log.e(TAG, "Failed to unregister config monitor", e); 120 } 121 } 122 } 123