/* * Copyright (C) 2006 The Android Open Source 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.server.policy; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.IUiModeManager; import android.app.ProgressDialog; import android.app.SearchManager; import android.app.StatusBarManager; import android.app.UiModeManager; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.database.ContentObserver; import android.graphics.PixelFormat; import android.graphics.Rect; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; import android.hardware.input.InputManagerInternal; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.AudioSystem; import android.media.IAudioService; import android.media.Ringtone; import android.media.RingtoneManager; import android.media.session.MediaSessionLegacyHelper; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.FactoryTest; import android.os.Handler; import android.os.IBinder; import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UEventObserver; import android.os.UserHandle; import android.os.Vibrator; import android.provider.MediaStore; import android.provider.Settings; import android.service.dreams.DreamManagerInternal; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.speech.RecognizerIntent; import android.telecom.TelecomManager; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; import android.util.MutableBoolean; import android.util.Slog; import android.util.SparseArray; import android.util.LongSparseArray; import android.view.Display; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.IApplicationToken; import android.view.IWindowManager; import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; import android.view.InputEventReceiver; import android.view.KeyCharacterMap; import android.view.KeyCharacterMap.FallbackAction; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.View; import android.view.ViewConfiguration; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import com.android.internal.R; import com.android.internal.logging.MetricsLogger; import com.android.internal.policy.PhoneWindow; import com.android.internal.policy.IShortcutService; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ScreenShapeHelper; import com.android.internal.widget.PointerLocationView; import com.android.server.GestureLauncherService; import com.android.server.LocalServices; import com.android.server.policy.keyguard.KeyguardServiceDelegate; import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; import com.android.server.statusbar.StatusBarManagerInternal; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.HashSet; import java.util.List; /* support the mouse mode */ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.NotificationChannel; import android.widget.Toast; import com.softwinner.Gpio; import com.softwinner.Multiir; //import android.hardware.display.DisplayManagerPolicy2; import java.lang.Runnable; /** * WindowManagerPolicy implementation for the Android phone UI. This * introduces a new method suffix, Lp, for an internal lock of the * PhoneWindowManager. This is used to protect some internal state, and * can be acquired with either the Lw and Li lock held, so has the restrictions * of both of those when held. */ public class TvWindowManager extends PhoneWindowManager { private final String TAG = "TvWindowManager"; private static final String FACTORY_TEST_APP= "com.softwinner.agingdragonbox"; /* support mute */ boolean mIsMute = false; private static final int NF_ID_ENTER_KEY_MOUSE_MODE = 1; boolean mKeyEnterMouseMode = false; NotificationManager mNotifationManager = null; Notification mNotificationEnterKeyMouseMode = null; Toast mMouseToast = null; ActivityManager mActivityManager; WindowState mFocusedTvWindow; Runnable mPromptEnterMouseMode = new Runnable() { public void run() { if (mMouseToast == null) { mMouseToast = Toast.makeText(mContext, com.android.internal.R.string.enter_key_mouse_mode, Toast.LENGTH_SHORT); if (mMouseToast == null) { Log.w(TAG, "Fail in creating toast."); } else { mMouseToast.setGravity(Gravity.CENTER, 0, 0); } } if (mMouseToast != null) { mMouseToast.setText(com.android.internal.R.string.enter_key_mouse_mode); mMouseToast.show(); } } }; Runnable mPromptExitMouseMode = new Runnable() { public void run() { if (mMouseToast == null) { mMouseToast = Toast.makeText(mContext, com.android.internal.R.string.exit_key_mouse_mode, Toast.LENGTH_SHORT); if (mMouseToast == null) { Log.w(TAG, "Fail in creating toast."); } else { mMouseToast.setGravity(Gravity.CENTER, 0, 0); } } if (mMouseToast != null) { mMouseToast.setText(com.android.internal.R.string.exit_key_mouse_mode); mMouseToast.show(); } } }; /* private DisplayManagerPolicy2 mDmPolicy; Toast mDisplayEnhanceToast; int mDisplayEnhance; boolean mDisplayEnhanceStay=true; String [] mDisplayEnhanceModeStrArray; static final int DISPALYMODE_SIZE = 3; Runnable mDisplayModeRunnable = new Runnable() { public void run() { int retEnhance; mHandler.removeCallbacks(mResetDisplayModeStay); mHandler.postDelayed(mResetDisplayModeStay, 5000); if (mDisplayEnhanceStay) { mDisplayEnhanceStay=false; mDisplayEnhance = mDmPolicy.getDisplay2EnhanceMode(0); retEnhance = mDisplayEnhance; mDisplayEnhance = mDisplayEnhance % DISPALYMODE_SIZE; } else { mDisplayEnhance++; mDisplayEnhance = mDisplayEnhance % DISPALYMODE_SIZE; retEnhance = mDmPolicy.setDisplay2EnhanceMode(0, mDisplayEnhance); } if (mDisplayEnhanceToast == null) { mDisplayEnhanceToast = Toast.makeText(mContext, "", Toast.LENGTH_LONG); } if (0 > retEnhance) { mDisplayEnhanceToast.setText("Enhance mode failed"); } else { mDisplayEnhanceToast.setText(mDisplayEnhanceModeStrArray[mDisplayEnhance]); } mDisplayEnhanceToast.show(); } }; Runnable mResetDisplayModeStay = new Runnable() { public void run() { mDisplayEnhanceStay = true; } }; */ private static final String ROOT_PROPERTY = "persist.vendor.root.enabled"; private static final String ADB_PROPERTY = "persist.vendor.adb.enabled"; private void switchRoot() { boolean enabled = SystemProperties.getBoolean(ROOT_PROPERTY, false); if (enabled) { SystemProperties.set(ROOT_PROPERTY, "0"); mHandler.post(new Runnable() { @Override public void run() { Toast.makeText(mContext, "Root disabled!", Toast.LENGTH_SHORT).show(); } }); } else { SystemProperties.set(ROOT_PROPERTY, "1"); mHandler.post(new Runnable() { @Override public void run() { Toast.makeText(mContext, "Root enabled!", Toast.LENGTH_SHORT).show(); } }); } } private void switchAdb() { boolean enabled = SystemProperties.getBoolean(ADB_PROPERTY, false); if (enabled) { SystemProperties.set(ADB_PROPERTY, "0"); mHandler.post(new Runnable() { @Override public void run() { Toast.makeText(mContext, "ADB disabled!", Toast.LENGTH_SHORT).show(); } }); } else { SystemProperties.set(ADB_PROPERTY, "1"); mHandler.post(new Runnable() { @Override public void run() { Toast.makeText(mContext, "ADB enabled!", Toast.LENGTH_SHORT).show(); } }); } } /** {@inheritDoc} */ @Override public void init(Context context, IWindowManager windowManager, WindowManagerFuncs windowManagerFuncs) { super.init(context, windowManager, windowManagerFuncs); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); context.registerReceiver(mFlickerIntentReceiver, filter); Resources resources = mContext.getResources(); mLedNormalFlicker = mContext.getResources().getInteger( com.android.internal.R.integer.config_ledNormalFlicker); mLedStandbyAllOff = mContext.getResources().getBoolean( com.android.internal.R.bool.config_ledStandbyAllOff); /* mDisplayEnhanceModeStrArray = mContext.getResources().getStringArray(com.android.internal.R.array.display2_enhance_mode_names); mDmPolicy = new DisplayManagerPolicy2(mContext); */ } private String pwd = ""; @Override public void onSystemUiStarted() { super.onSystemUiStarted(); Multiir.registerObserver(mContext); } @Override public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { super.interceptKeyBeforeDispatching(win, event, policyFlags); final boolean keyguardOn = keyguardOn(); final int keyCode = event.getKeyCode(); final int repeatCount = event.getRepeatCount(); final int metaState = event.getMetaState(); final int flags = event.getFlags(); final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; final boolean canceled = event.isCanceled(); if(down && keyCode != KeyEvent.KEYCODE_POWER && keyCode != KeyEvent.KEYCODE_UNKNOWN){ startFlicker(); } if (down) { pwd += String.valueOf(keyCode); if (pwd.contains("1412151298")) { // factory test(password 758521) startApp("com.oranth.factory", "com.oranth.factory.MainActivity"); pwd = ""; } else if (pwd.contains("1412151299")) { // root switch(password 758522) switchRoot(); pwd = ""; } else if (pwd.contains("14121512910")) { // adb switch(password 758523) switchAdb(); pwd = ""; } if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_UP) { pwd = ""; } } if (keyCode == KeyEvent.KEYCODE_MOUSE) { Log.v(TAG, "it's KEYCODE_MOUSE key and down = " + down); if (!down) { if (mNotifationManager == null) { mNotifationManager = (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); if (mNotifationManager == null) { Log.w(TAG, "Fail in get NotificationManager"); return -1; } } if (mNotificationEnterKeyMouseMode == null) { NotificationChannel channel = new NotificationChannel("TvWindow_Mouse", "MouseChannel", NotificationManager.IMPORTANCE_DEFAULT); channel.setSound(null, null); mNotifationManager.createNotificationChannel(channel); Intent intent = new Intent(); PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); mNotificationEnterKeyMouseMode = new Notification.Builder(mContext).setWhen(System.currentTimeMillis()) .setTicker(mContext.getResources().getText(com.android.internal.R.string.enter_key_mouse_mode)) .setSmallIcon(com.android.internal.R.drawable.key_mouse) .setContentIntent(contentIntent) .setContentTitle(mContext.getResources().getText(com.android.internal.R.string.title_key_mouse_mode)) .setContentText(mContext.getResources().getText(com.android.internal.R.string.detail_key_mouse_mode)) .setChannel("TvWindow_Mouse").build(); } if (mKeyEnterMouseMode) { mNotifationManager.cancel(NF_ID_ENTER_KEY_MOUSE_MODE); mHandler.removeCallbacks(mPromptExitMouseMode); mHandler.post(mPromptExitMouseMode); Multiir.exitMouseMode(); mKeyEnterMouseMode = false; } else { mNotifationManager.notify(NF_ID_ENTER_KEY_MOUSE_MODE, mNotificationEnterKeyMouseMode); mHandler.removeCallbacks(mPromptEnterMouseMode); mHandler.post(mPromptEnterMouseMode); Multiir.enterMouseMode(); mKeyEnterMouseMode = true; } } return -1; } return 0; } private Handler mFlickerHandler = new Handler(); private boolean mFlickerEnable = true; private static final int FLICKER_INTERVAL = 50; private static final char portType = 'h'; private static final int portNum = 20; private static final int on = 1; private static final int off = 0; private int mLedNormalFlicker; private boolean mLedStandbyAllOff; private BroadcastReceiver mFlickerIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Slog.d(TAG, "action = " + action); if (action.equals(Intent.ACTION_SCREEN_ON)) { Slog.d(TAG,"================================================== ACTION_SCREEN_ON"); mFlickerEnable = true; mFlickerHandler.removeCallbacks(mStep1On); mFlickerHandler.removeCallbacks(mStep2Off); mFlickerHandler.removeCallbacks(mStep3On); Gpio.setNormalLedOn(true); Gpio.setStandbyLedOn(false); }else if (action.equals(Intent.ACTION_SCREEN_OFF)) { Slog.d(TAG,"================================================== ACTION_SCREEN_OFF"); mFlickerEnable = false; mFlickerHandler.removeCallbacks(mStep1On); mFlickerHandler.removeCallbacks(mStep2Off); mFlickerHandler.removeCallbacks(mStep3On); if(mLedStandbyAllOff == false) { Gpio.setNormalLedOn(false); Gpio.setStandbyLedOn(true); } else { Gpio.setNormalLedOn(false); Gpio.setStandbyLedOn(false); } } } }; private void startFlicker() { Slog.d("GpioService", "mFlickerEnable = " + mFlickerEnable); if (mFlickerEnable) { //Gpio.setNormalLedOn(false); //Gpio.setStandbyLedOn(false); mFlickerHandler.removeCallbacks(mStep1On); mFlickerHandler.removeCallbacks(mStep2Off); mFlickerHandler.removeCallbacks(mStep3On); mFlickerHandler.postDelayed(mStep1On, FLICKER_INTERVAL); } } private Runnable mStep1On = new Runnable() { public void run() { if (mFlickerEnable) { Gpio.setNormalLedOn(true); Gpio.setStandbyLedOn(false); mFlickerHandler.removeCallbacks(mStep2Off); mFlickerHandler.removeCallbacks(mStep3On); mFlickerHandler.postDelayed(mStep2Off, FLICKER_INTERVAL); } } }; private Runnable mStep2Off = new Runnable() { public void run() { if (mFlickerEnable) { if (mLedNormalFlicker == 0) { Gpio.setNormalLedOn(true); Gpio.setStandbyLedOn(false); } else if (mLedNormalFlicker == 1) { Gpio.setNormalLedOn(true); Gpio.setStandbyLedOn(true); } else if (mLedNormalFlicker == 2) { Gpio.setNormalLedOn(false); Gpio.setStandbyLedOn(false); } else if (mLedNormalFlicker == 3) { Gpio.setNormalLedOn(false); Gpio.setStandbyLedOn(true); } mFlickerHandler.removeCallbacks(mStep3On); mFlickerHandler.postDelayed(mStep3On, FLICKER_INTERVAL); } } }; private Runnable mStep3On = new Runnable() { public void run() { if (mFlickerEnable) { Gpio.setNormalLedOn(true); Gpio.setStandbyLedOn(false); } } }; @Override public void onDefaultDisplayFocusChangedLw(WindowState newFocus) { super.onDefaultDisplayFocusChangedLw(newFocus); mFocusedTvWindow = newFocus; } private int startApp(String propertyPkg, Bundle bundle) { Intent launchIntent; PackageManager packageManager = mContext.getPackageManager(); String packageName = SystemProperties.get(propertyPkg); if ((packageName == null) || (packageName.length() == 0)) { Log.e(TAG, "[startApp] propertyPkg: " + propertyPkg + " is empty!"); return -1; } launchIntent = packageManager.getLaunchIntentForPackage(packageName); if (launchIntent == null) { launchIntent = packageManager.getLeanbackLaunchIntentForPackage(packageName); if (launchIntent == null) { Log.e(TAG, "[startApp] can not get intent for package: " + packageName); return -1; } } if (bundle != null) launchIntent.putExtras(bundle); mContext.startActivity(launchIntent); return 0; } private int startApp(String propertyPkg) { Bundle bundle = null; return startApp(propertyPkg, bundle); } private int startApp(String propertyPkg, String propertyCls, Bundle bundle) { Intent intent = new Intent(); intent.setComponent(new ComponentName(propertyPkg, propertyCls)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (bundle != null) intent.putExtras(bundle); mContext.startActivity(intent); return 0; } private int startApp(String propertyPkg, String propertyCls) { return startApp(propertyPkg, propertyCls, null); } @Override public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { int keyCode = event.getKeyCode(); final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; Log.d(TAG,"key event key = " + KeyEvent.keyCodeToString(keyCode)); if (down) { switch (keyCode) { case KeyEvent.KEYCODE_SETTINGS: Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.tv.settings", "com.android.tv.settings.MainSettings")); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); break; case KeyEvent.KEYCODE_APPS: if (mActivityManager == null) mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE); ComponentName cn = mActivityManager.getRunningTasks(1).get(0).topActivity; String ActivityName = cn.getClassName(); Log.d(TAG, "current activity is " + ActivityName); if (ActivityName.contains("launcher.device.apps.AppsActivity")) break; Intent app_intent = new Intent(); app_intent.setComponent(new ComponentName("com.android.tv.launcher", "com.android.tv.launcher.device.apps.AppsActivity")); app_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(app_intent); break; case KeyEvent.KEYCODE_PROG_RED: Log.d(TAG,"key event red"); //mHandler.post(mDisplayModeRunnable); break; case KeyEvent.KEYCODE_PROG_GREEN: Log.d(TAG,"key event greed"); launchHomeFromHotKey(mDefaultDisplay.getDisplayId()); break; case KeyEvent.KEYCODE_PROG_YELLOW: Log.d(TAG,"key event yellow"); Intent intent1 = new Intent(); intent1.setComponent(new ComponentName("com.android.settings", "com.android.settings.Settings")); intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent1); break; case KeyEvent.KEYCODE_PROG_BLUE: Log.d(TAG,"key event blue"); if (mFocusedTvWindow != null && !"com.softwinner.TvdFileManager".equals(mFocusedTvWindow.getOwningPackage())) { Intent intent2 = new Intent(); intent2.setComponent(new ComponentName("com.softwinner.TvdFileManager", "com.softwinner.TvdFileManager.MainUI")); intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent2); } break; case KeyEvent.KEYCODE_MUTE: case KeyEvent.KEYCODE_VOLUME_MUTE: Log.d(TAG, "key Mute"); handleMute(keyCode); //cmcc break; case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: Log.d(TAG,"mIsMute = " + mIsMute); if (mIsMute) { handleMute(keyCode); //cmcc } break; case KeyEvent.KEYCODE_MOVIE: Log.v(TAG, "it's KEYCODE_MOVIE key and down = " + down); if (mFocusedTvWindow != null && !"com.softwinner.TvdFileManager".equals(mFocusedTvWindow.getOwningPackage())) { Intent intent3 = new Intent(); intent3.setComponent(new ComponentName("com.softwinner.TvdFileManager", "com.softwinner.TvdFileManager.MainUI")); intent3.putExtra("media_type", "MEDIA_TYPE_VIDEO"); intent3.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent3); } break; } } else {//key up switch (keyCode) { case KeyEvent.KEYCODE_HOME: if (mFocusedTvWindow != null) { String focusedWindowApp = mFocusedTvWindow.getOwningPackage(); Log.d(TAG,"the focus window is "+focusedWindowApp); if (focusedWindowApp.equals(FACTORY_TEST_APP)) { return 0; } }else{ Log.v(TAG, "the mFocusedWindow is null"); } break; } } return super.interceptKeyBeforeQueueing(event,policyFlags); } void handleMute(int keyCode) { IAudioService audioService = getAudioService(); final AudioManager mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); if (audioService == null) { return; } mBroadcastWakeLock.acquire(); switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_MUTE: case KeyEvent.KEYCODE_MUTE: mAudioManager.setMasterMute((mIsMute = !mIsMute),AudioManager.FLAG_SHOW_UI); break; default: break; } //mute the ir key sound if (!mIsMute) { mAudioManager.loadSoundEffects(); } else { mAudioManager.unloadSoundEffects(); } Settings.System.putInt(mContext.getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED, !mIsMute ? 1 : 0); mBroadcastWakeLock.release(); } }