
ãã®èšäºã§ã¯ãã¡ã€ã³ã®Androidã¢ããªã±ãŒã·ã§ã³ã§ããSystemUIã®ã¢ãŒããã¯ãã£ãšåäœåçãåæããŸãã ãã®ãããã¯ã«èå³ããã£ãã®ã¯ãã·ã¹ãã ãã©ã®ããã«æ©èœããã®ãçåã ããã§ãããã®ã·ã¹ãã ã¯èšå€§ãªæ°ã®ãŠãŒã¶ãŒã«ãã£ãŠäœ¿çšãããGoogle PlayãŸãã¯åã«ã€ã³ã¿ãŒãããã§æ¯æ¥äœåãã®ã¢ããªã±ãŒã·ã§ã³ãããŠã³ããŒããããŸãã ããã«ãAndroidã®æ å ±ã»ãã¥ãªãã£ã®åé¡ãšããã®ããã«äœæãããã¢ããªã±ãŒã·ã§ã³ã«ãèå³ããããŸãã
Androidã§ã¯ãSystemUIã¯ãœãŒã¹ã³ãŒããã¹ãplatform_frameworks_base / packages / SystemUI /ã«ããã¢ããªã±ãŒã·ã§ã³ã§ãããããã€ã¹ã§ã¯system / priv-app / -SystemUIã«ãããŸãã
priv-appã¯ãç¹æš©ã¢ããªã±ãŒã·ã§ã³ãä¿åããããã£ã¬ã¯ããªã§ãã ãšããã§ãã·ã¹ãã /ã¢ããªã®ãã¹ã«æ²¿ã£ãŠããªã€ã³ã¹ããŒã«ãããã¢ããªã±ãŒã·ã§ã³ããããèªåã§ããã€ã¹ã«ã€ã³ã¹ããŒã«ããéåžžã®ã¢ããªã±ãŒã·ã§ã³ã¯ããŒã¿/ã¢ããªã«ä¿åãããŸãã
ããã¯ããã«çåãæèµ·ããŸãããã¹ãŠã®ããªã€ã³ã¹ããŒã«ãããç¹æš©ã¢ããªã±ãŒã·ã§ã³ã1ã€ã®ãã£ã¬ã¯ããªã«ããã·ã¥ã§ããªãã®ã¯ãªãã§ããããªããã®åé¢ãå¿ èŠãªã®ã§ããïŒ
å®éãäžéšã®ã¢ããªã±ãŒã·ã§ã³ã¯ä»ã®ã¢ããªã±ãŒã·ã§ã³ãããäœç³»çã§ã:)ãããŠãä¿è·ãããæäœã«ã¢ã¯ã»ã¹ããããã«ãã·ã¹ãã ã¢ããªã±ãŒã·ã§ã³ã®ãšã¯ã¹ããã€ãã«ãã¬ããžãæžããããã«ããã®åé¢ãå¿ èŠã§ãã ç¹å¥ãªApplicationInfo.FLAG_SYSTEMãæã€ã¢ããªã±ãŒã·ã§ã³ãäœæããã·ã¹ãã ã§ããå€ãã®æš©éãååŸã§ããŸããããã®æš©éãæã€apkãã¡ã€ã«ã¯ã·ã¹ãã ã»ã¯ã·ã§ã³ã«é 眮ãããŸãã
ãã®ãããSystemUIã¯apkãã¡ã€ã«ã§ãããæ¬è³ªçã«ã¯éåžžã®ã¢ããªã±ãŒã·ã§ã³ã§ãã ãã ããè€éãªSystemUIããã€ã¹ãèŠããšãåçŽãªã¢ããªã±ãŒã·ã§ã³ã®ããã«èŠããªããªããŸãããïŒ
ãã®ã¢ããªã±ãŒã·ã§ã³ã¯éåžžã«éèŠãªæ©èœãå®è¡ããŸãã
- ããã²ãŒã·ã§ã³
- æè¿ã®ã¢ããªã±ãŒã·ã§ã³
- ã¯ã€ãã¯èšå®
- éç¥ããŒ
- ããã¯ç»é¢
- é³é調ç¯
- ããŒã ç»é¢
- ...
SystemUIãèµ·åãã
äžèšã§è¿°ã¹ãããã«ãSystemUIã¯éåžžã®ã¢ããªã±ãŒã·ã§ã³ãšã¯ç°ãªããŸãããã®ãããã»ãšãã©ã®ã¢ããªã±ãŒã·ã§ã³ã®å Žåã®ããã«ããã®èµ·åã¯ã¢ã¯ãã£ããã£ã®èµ·åã䌎ããŸããã SystemUIã¯ãã·ã¹ãã ããŒãããã»ã¹äžã«èµ·åããå®äºã§ããªãã°ããŒãã«ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã§ãã
<application android:name=".SystemUIApplication" android:persistent="true" android:allowClearUserData="false" android:allowBackup="false" android:hardwareAccelerated="true" android:label="@string/app_label" android:icon="@drawable/icon" android:process="com.android.systemui" android:supportsRtl="true" android:theme="@style/Theme.SystemUI" android:defaultToDeviceProtectedStorage="true" android:directBootAware="true" android:appComponentFactory="androidx.core.app.CoreComponentFactory">
Androidã®äžçã®2ã€ã®æ±ã®1ã€ã§ããSystemServerã«ã¢ã¯ã»ã¹ãããš ïŒ2çªç®ã¯Zygoteã§ãããããã«ã€ããŠã¯åŸã§èª¬æããŸãïŒãã·ã¹ãã ã®èµ·åæã«SystemUIãéå§ãããå ŽæãèŠã€ããããšãã§ããŸãã
static final void startSystemUi(Context context, WindowManagerService windowManager) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.SYSTEM); windowManager.onSystemUiStarted(); }
ããã§ã¯ãéãããªãã¯API startServiceAsUserã䜿çšããŠSystemUIãµãŒãã¹ãéå§ããæ¹æ³ã確èªããŸãã ããã䜿çšãããå Žåãåå°ã«é Œããªããã°ãªããŸããã ããããAndroidã§ãªãã¬ã¯ã·ã§ã³APIã䜿çšããããšã«æ±ºããå Žåãããã䟡å€ããããã©ãããäœåºŠãèããŠãã ããã
ãã®ãããããã§ã¯ã¢ããªã±ãŒã·ã§ã³çšã«åå¥ã®ããã»ã¹ãäœæããŸããå®éã SystemUIã®åã»ã¯ã·ã§ã³ã¯åå¥ã®ãµãŒãã¹ãŸãã¯ç¬ç«ããã¢ãžã¥ãŒã«ã§ãã
public abstract class SystemUI implements SysUiServiceProvider { public Context mContext; public Map<Class<?>, Object> mComponents; public abstract void start(); protected void onConfigurationChanged(Configuration newConfig) { } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { } protected void onBootCompleted() { } @SuppressWarnings("unchecked") public <T> T getComponent(Class<T> interfaceType) { return (T) (mComponents != null ? mComponents.get(interfaceType) : null); } public <T, C extends T> void putComponent(Class<T> interfaceType, C component) { if (mComponents != null) { mComponents.put(interfaceType, component); } } public static void overrideNotificationAppName(Context context, Notification.Builder n, boolean system) { final Bundle extras = new Bundle(); String appName = system ? context.getString(com.android.internal.R.string.notification_app_name_system) : context.getString(com.android.internal.R.string.notification_app_name_settings); extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName); n.addExtras(extras); } }
startïŒïŒã¡ãœãããåŒã³åºãããŠã以äžã«ãªã¹ããããŠããåãµãŒãã¹ãéå§ãããŸãã
<string-array name="config_systemUIServiceComponents" translatable="false"> <item>com.android.systemui.Dependency</item> <item>com.android.systemui.util.NotificationChannels</item> <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item> <item>com.android.systemui.keyguard.KeyguardViewMediator</item> <item>com.android.systemui.recents.Recents</item> <item>com.android.systemui.volume.VolumeUI</item> <item>com.android.systemui.stackdivider.Divider</item> <item>com.android.systemui.SystemBars</item> <item>com.android.systemui.usb.StorageNotification</item> <item>com.android.systemui.power.PowerUI</item> <item>com.android.systemui.media.RingtonePlayer</item> <item>com.android.systemui.keyboard.KeyboardUI</item> <item>com.android.systemui.pip.PipUI</item> <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item> <item>@string/config_systemUIVendorServiceComponent</item> <item>com.android.systemui.util.leak.GarbageMonitor$Service</item> <item>com.android.systemui.LatencyTester</item> <item>com.android.systemui.globalactions.GlobalActionsComponent</item> <item>com.android.systemui.ScreenDecorations</item> <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item> <item>com.android.systemui.SliceBroadcastRelayHandler</item> </string-array>
é³é調ç¯
ããã€ã¹ã®ããªã¥ãŒã ãã¿ã³ãå®æçã«äœ¿çšããŸããããµãŠã³ããè¿œå ãŸãã¯ãªãã«ã§ããããã«ãã·ã¹ãã ã§çºçããããã»ã¹ã«ã€ããŠã¯èããŸããã æäœã¯èšèã§ã¯éåžžã«ç°¡åã«æããŸããã SystenUI / volumeã®ãµããã©ã«ããŒã«ããVolumeUIãèŠããšãã€ã³ã¿ãŒãã§ã€ã¹ã«ã¯ããŸããŸãªã¢ãŒãã§ç¬èªã®ããªãšãŒã·ã§ã³ããããŸãã

SystemUIãµãŒãã¹ã¯startïŒïŒã¡ãœããã«ãã£ãŠéå§ããããšæ¢ã«è¿°ã¹ãŸããã VolumeUIã¯ã©ã¹ãèŠããšã SystemUIãããç¶æ¿ããŠããŸãã
public class VolumeUI extends SystemUI { private static final String TAG = "VolumeUI"; private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG); private final Handler mHandler = new Handler(); private boolean mEnabled; private VolumeDialogComponent mVolumeComponent; @Override public void start() { boolean enableVolumeUi = mContext.getResources().getBoolean(R.bool.enable_volume_ui); boolean enableSafetyWarning = mContext.getResources().getBoolean(R.bool.enable_safety_warning); mEnabled = enableVolumeUi || enableSafetyWarning; if (!mEnabled) return; mVolumeComponent = new VolumeDialogComponent(this, mContext, null); mVolumeComponent.setEnableDialogs(enableVolumeUi, enableSafetyWarning); putComponent(VolumeComponent.class, getVolumeComponent()); setDefaultVolumeController(); } âŠ
ããã§ãmEnabledã䜿çšããŠããµãŠã³ãèšå®ã®ããããã«ã衚瀺ãããã©ããã決å®ããããšãããããŸãã ãããŠãVolumeDialogComponentã«ãã£ãŠå€æãããšãVolumeUIã¯ãµãŠã³ãããŒããã€ã¢ãã°ãšããŠè¡šç€ºããŸãã ãã ããé³éããŒã®æŒäžã«é¢ãããã¹ãŠã®ã¢ã¯ã·ã§ã³ã¯PhoneWindowã§åŠçãããŸã ã
protected boolean onKeyDown(int featureId, int keyCode, KeyEvent event) { ... switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_MUTE: { // If we have a session send it the volume command, otherwise // use the suggested stream. if (mMediaController != null) { mMediaController.dispatchVolumeButtonEventAsSystemService(event); } else { getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(event, mVolumeControlStreamType); } return true; } ... protected boolean onKeyUp(int featureId, int keyCode, KeyEvent event) { final KeyEvent.DispatcherState dispatcher = mDecor != null ? mDecor.getKeyDispatcherState() : null; if (dispatcher != null) { dispatcher.handleUpEvent(event); } //Log.i(TAG, "Key up: repeat=" + event.getRepeatCount() // + " flags=0x" + Integer.toHexString(event.getFlags())); switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_DOWN: { // If we have a session send it the volume command, otherwise // use the suggested stream. if (mMediaController != null) { mMediaController.dispatchVolumeButtonEventAsSystemService(event); } else { getMediaSessionManager().dispatchVolumeKeyEventAsSystemService( event, mVolumeControlStreamType); } return true; } âŠ
ã芧ã®ãšãããKEYCODE_VOLUME_UPïŒ+ïŒã¯åŠçããããKEYCODE_VOLUME_DOWNïŒ-ïŒã®åŠçã«å ¥ããŸãã onKeyDownãšonKeyUpã®äž¡æ¹ã®ã€ãã³ãã§ã dispatchVolumeButtonEventAsSystemServiceã¡ãœãããåŒã³åºãããŸãã
public void dispatchVolumeButtonEventAsSystemService(@NonNull KeyEvent keyEvent) { switch (keyEvent.getAction()) { case KeyEvent.ACTION_DOWN: { int direction = 0; switch (keyEvent.getKeyCode()) { case KeyEvent.KEYCODE_VOLUME_UP: direction = AudioManager.ADJUST_RAISE; break; ... mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, true, direction, ... }
ãã®ãããããã§ã¯adjustVolumeã¡ãœãããåŒã³åºããŠãã€ãã³ããã©ã¡ãŒã¿ãå²ãåœãŠãããæ¹åã確èªã§ããããã«ããŸãã
ãã®çµæã AudioServiceã«å°éãããšã sendVolumeUpdateãåŒã³åºãããpostVolumeChangedã¡ãœããã®åŒã³åºãã«å ããŠãHDMIã€ã³ã¿ãŒãã§ã€ã¹ãã€ã³ã¹ããŒã«ãããŸãã
// UI update and Broadcast Intent protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) { ... mVolumeController.postVolumeChanged(streamType, flags); } private int updateFlagsForSystemAudio(int flags) { ... if (mHdmiSystemAudioSupported && ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) { flags &= ~AudioManager.FLAG_SHOW_UI; } ... } return flags; } public void postVolumeChanged(int streamType, int flags) { ... mController.volumeChanged(streamType, flags); ... }
çã¡ã
Androidã®RingtonePlayerã¯ãã¬ãŒã€ãŒãšããŠæ©èœããŸãã ãŸããSystemUIãç¶æ¿ãã startïŒïŒã¡ãœããã«æ¬¡ã®ããã«è¡šç€ºãããŸãã
@Override public void start() { ... mAudioService.setRingtonePlayer(mCallback); ... }
ããã§ã¯ãæ¬è³ªçã«IRingtonePlayerã®ã€ã³ã¹ã¿ã³ã¹ã§ããmCallbackãã€ã³ã¹ããŒã«ããŸãã
private IRingtonePlayer mCallback = new IRingtonePlayer.Stub() { @Override public void play(IBinder token, Uri uri, AudioAttributes aa, float volume, boolean looping) throws RemoteException { ... } @Override public void stop(IBinder token) { ... } @Override public boolean isPlaying(IBinder token) { ... } @Override public void setPlaybackProperties(IBinder token, float volume, boolean looping) { ... } @Override public void playAsync(Uri uri, UserHandle user, boolean looping, AudioAttributes aa) { ... } @Override public void stopAsync() { ... } @Override public String getTitle(Uri uri) { ... } @Override public ParcelFileDescriptor openRingtone(Uri uri) { ... } };
æåŸã«ããã€ã³ããŒã䜿çšããŠRingtonePlayerServiceãå¶åŸ¡ãããªãŒãã£ãªãã¡ã€ã«ãåçã§ããŸãã
ãã¯ãŒã€
PowerUIã¯ãé»æºç®¡çãšéç¥ãæ åœããŸãã SystemUIããåæ§ã«ç¶æ¿ãããstartïŒïŒã¡ãœããããããŸãã
public void start() { mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mHardwarePropertiesManager = (HardwarePropertiesManager) mContext.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE); mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime(); mWarnings = Dependency.get(WarningsUI.class); mEnhancedEstimates = Dependency.get(EnhancedEstimates.class); mLastConfiguration.setTo(mContext.getResources().getConfiguration()); ContentObserver obs = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { updateBatteryWarningLevels(); } }; final ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL), false, obs, UserHandle.USER_ALL); updateBatteryWarningLevels(); mReceiver.init(); showThermalShutdownDialog(); initTemperatureWarning(); }
äžèšã®ã³ãŒããããããããã«ãSettings.Global.LOW_POWER_MODE_TRIGGER_LEVELã®å€æŽããµãã¹ã¯ã©ã€ãããããã®åŸã mReceiver.initïŒïŒã®åŒã³åºããåŒã³åºãããŸãã
public void init() { // Register for Intent broadcasts for... IntentFilter filter = new IntentFilter(); filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(this, filter, null, mHandler); }
ããã§ããããŒããã£ã¹ãã¬ã·ãŒããŒãç»é²ããããã®å©ããåããŠå€æŽè¿œè·¡ãå®è¡ãããŸãã
ã¿ã¹ã¯
Recentsã¯ãAndroidã¢ãã€ã«ããã€ã¹ã§äž»ã«äœ¿çšãããæ©èœã§ãã
äž»ãªæ©èœïŒ
- ãã¹ãŠã®ã¿ã¹ã¯ã衚瀺ãã
- ã¿ã¹ã¯ãåãæ¿ãã
- ã¿ã¹ã¯ãåé€ãã
ããã«ãRecentsãSystemUIããç¶æ¿ãããŸãã RecentsActivityã¯ãææ°ã®ã¿ã¹ã¯ãäœæããã³æŽæ°ããŠãç»é¢ã«è¡šç€ºã§ããããã«ããŸãã

RecentTaskInfoã䜿çšãããšãç¹å®ã®ã¿ã¹ã¯ã«é¢ããæ å ±ãååŸã§ããŸãã
public static class RecentTaskInfo implements Parcelable { public int id; public int persistentId; public Intent baseIntent; public ComponentName origActivity; public ComponentName realActivity; public CharSequence description; public int stackId; ...
äžè¬ã«ãå®è¡äžã®ã¿ã¹ã¯ã¯å¥ã®ãããã¯ã«é 眮ã§ããŸãã ã¢ããªã±ãŒã·ã§ã³ãããã¯ã°ã©ãŠã³ãã«åãæ¿ããåã«ã¢ããªã±ãŒã·ã§ã³ç»é¢ããŒããããšã§ãRecentsTaskã«èªã¿åãäžèœãªããŒãžã§ã³ã®ã¹ãããã·ã§ããã衚瀺ãããããã«ããã®ã§ãããããåŽé¢ãã調æ»ããŸããã ãã ããåé¡ã¯ãonPauseïŒïŒãåŒã³åºãããåã«ã¢ããªã±ãŒã·ã§ã³ã¹ãããã·ã§ãããååŸãããããšã§ãã ãã®åé¡ã¯ããã€ãã®æ¹æ³ã§è§£æ±ºã§ããŸãã ãŸãã¯ãã·ã¹ãã ãåã«ç»é¢ã®å 容ãé衚瀺ã«ããããã«ãã©ã°ãèšå®ããŸã
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
ã¹ãããã·ã§ããã«é¢ãã以åã®èšäºã§è©±ããããšã
éåžžãã¢ããªã±ãŒã·ã§ã³ã®ç¹å®ã®ã¢ã¯ãã£ããã£ãã¿ã¹ã¯ã«è¡šç€ºãããªãããã«ããã«ã¯ããããã§ã¹ããæ¿å ¥ããŸã
android:excludeFromRecents = "true"
ãŸãã¯ããã®ããªãã¯ã䜿çšã§ããŸã
Intent.FLAG_ACTIVITY_MULTIPLE_TASK
ãã©ã°excludeFromRecents = trueã®äžã«ã¡ã€ã³ã¢ã¯ãã£ããã£ãèšå®ããŠãç»é¢ãå®è¡äžã®ã¿ã¹ã¯ã«ãªãããã«ããããšãã§ããŸãããã¢ããªã±ãŒã·ã§ã³ãèªã¿èŸŒãŸãããšãã¡ã€ã³ã¢ã¯ãã£ããã£ã®ãŒãããã¹ã¯ãªãŒã³ã·ã§ãããŸãã¯ãã®ä»ã®ç»åã衚瀺ããå¥ã®ã¿ã¹ã¯ãå®è¡ããŸãã 詳现ã«ã€ããŠã¯ãGoogleãã©ã€ãã®äŸã«é¢ããå ¬åŒããã¥ã¡ã³ãã§èª¬æããŠããŸãã
ããã¯ç»é¢
ããŒã¬ãŒãã¯ããã§ã«äžèšã®ãã¹ãŠã®ã¢ãžã¥ãŒã«ãããè€éã§ãã SystemUIã§å®è¡ããããµãŒãã¹ã§ãããKeyguardViewMediatorã䜿çšããŠç®¡çãããŸãã
private void setupLocked() { ... // Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard // is disabled. if (mContext.getResources().getBoolean( com.android.keyguard.R.bool.config_enableKeyguardService)) { setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled( KeyguardUpdateMonitor.getCurrentUser()), mAodShowing, mSecondaryDisplayShowing, true /* forceCallbacks */); } else { // The system's keyguard is disabled or missing. setShowingLocked(false, mAodShowing, mSecondaryDisplayShowing, true); } ... mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0); String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND); if (soundPath != null) { mLockSoundId = mLockSounds.load(soundPath, 1); } ... int lockSoundDefaultAttenuation = mContext.getResources().getInteger( com.android.internal.R.integer.config_lockSoundVolumeDb); mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20); ... }
ãã ããå®éã«ã¯ãKeyguardServiceã¯ããã¯ç»é¢ã€ã³ã¿ãŒãã§ã€ã¹ãšã¯ç¬ç«ããŠæ©èœãããæ å ±ãStatusBarã¢ãžã¥ãŒã«ã«è»¢éããã ãã§ããStatusBarã¢ãžã¥ãŒã«ã§ã¯ãç»é¢ã®èŠèŠçãªå€èŠ³ãšæ å ±ã®è¡šç€ºã«é¢ããã¢ã¯ã·ã§ã³ãæ¢ã«å®è¡ãããŠããŸãã
éç¥ããŒ
SystemBarsã«ã¯ãããªãè€éãªããã€ã¹ãšæ§é ããããŸãã 圌ã®ä»äºã¯2ã€ã®æ®µéã«åãããŠããŸãã
- SystemBarsã®åæå
- éç¥ã衚瀺ãã
SystemBarsã®èµ·åãèŠããš
private void createStatusBarFromConfig() { ... final String clsName = mContext.getString(R.string.config_statusBarComponent); ... cls = mContext.getClassLoader().loadClass(clsName); ... mStatusBar = (SystemUI) cls.newInstance(); ... }
次ã«ãã¯ã©ã¹åãèªã¿åãããã€ã³ã¹ã¿ã³ã¹ãäœæããããªãœãŒã¹ãžã®ãªã³ã¯ã衚瀺ãããŸãã
<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>
ãããã£ãŠãããã§ã¯StatusBarãåŒã³åºãããéç¥ãšUIã®åºåã§æ©èœããããšãããããŸãã
Androidã¯éåžžã«è€éã§ãèšå€§ãªæ°ã®ã³ãŒãè¡ã«èšè¿°ãããŠããå€ãã®ããªãã¯ãå«ãŸããŠããããšãçã人ã¯ããªããšæããŸãã SystemUIã¯ãã®ã·ã¹ãã ã®æãéèŠãªéšåã®1ã€ã§ãããç§ã¯ããã«ã€ããŠåŠã¶ããšã楜ãã¿ãŸããã ãã®ãããã¯ã«é¢ããè³æã¯ã»ãšãã©ãªãããããšã©ãŒã«æ°ã¥ããå Žåã¯ä¿®æ£ããŠãã ããã
PSç§ã¯ããã¬ã°ã©ã ã®@paradisecurityã«é¢ããçŽ æã®éžæãšçãèšäºãåžžã«å ¬éããŠããŸãã