zoukankan      html  css  js  c++  java
  • RK3399 Android7.1 系统打印方案(二)无.预览打印

    一.调用系统打印预览demo  PrintManager

    1.1.系统预览打印界面

    .a.AndroidManifest.xml

        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

    .b.MyPrintAdapter.java

    package com.gatsby.printdemo;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Matrix;
    import android.graphics.Paint;
    import android.graphics.pdf.PdfDocument;
    import android.graphics.pdf.PdfDocument.PageInfo;
    import android.graphics.pdf.PdfRenderer;
    import android.os.Bundle;
    import android.os.CancellationSignal;
    import android.os.ParcelFileDescriptor;
    import android.print.PageRange;
    import android.print.PrintAttributes;
    import android.print.PrintDocumentAdapter;
    import android.print.PrintDocumentInfo;
    import android.print.pdf.PrintedPdfDocument;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    
    public class MyPrintAdapter extends PrintDocumentAdapter {
    
        private Context context;
        private int pageHeight;
        private int pageWidth;
        private PdfDocument mPdfDocument;
        private int totalpages = 1;
        private String pdfPath;
        private List<Bitmap> mlist;
    
        public MyPrintAdapter(Context context,String pdfPath) {
            this.context = context;
            this.pdfPath = pdfPath;
        }
    
        @Override
        public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal,
                             LayoutResultCallback callback,
                             Bundle metadata) {
    
            mPdfDocument = new PrintedPdfDocument(context, newAttributes); //创建可打印PDF文档对象
    
            pageHeight = newAttributes.getMediaSize().ISO_A4.getHeightMils() * 72 / 1000;  //设置尺寸
            pageWidth = newAttributes.getMediaSize().ISO_A4.getWidthMils() * 72 / 1000;
    
            if (cancellationSignal.isCanceled()) {
                callback.onLayoutCancelled();
                return;
            }
    
            ParcelFileDescriptor mFileDescriptor = null;
            PdfRenderer pdfRender = null;
            PdfRenderer.Page page = null;
            try {
                mFileDescriptor = ParcelFileDescriptor.open(new File(pdfPath), ParcelFileDescriptor.MODE_READ_ONLY);
                if (mFileDescriptor != null)
                    pdfRender = new PdfRenderer(mFileDescriptor);
    
                mlist = new ArrayList<>();
    
                if (pdfRender.getPageCount() > 0) {
                    totalpages = pdfRender.getPageCount();
                    for (int i = 0; i < pdfRender.getPageCount(); i++) {
                        if(null != page)
                            page.close();
                        page = pdfRender.openPage(i);
                        Bitmap bmp = Bitmap.createBitmap(page.getWidth()*2,page.getHeight()*2, Bitmap.Config.ARGB_8888);
                        page.render(bmp, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
                        mlist.add(bmp);
                    }
                }
                if(null != page)
                    page.close();
                if(null != mFileDescriptor)
                    mFileDescriptor.close();
                if (null != pdfRender)
                    pdfRender.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            if (totalpages > 0) {
                PrintDocumentInfo.Builder builder = new PrintDocumentInfo
                        .Builder("快速入门.pdf")
                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
                        .setPageCount(totalpages);  //构建文档配置信息
    
                PrintDocumentInfo info = builder.build();
                callback.onLayoutFinished(info, true);
            } else {
                callback.onLayoutFailed("Page count is zero.");
            }
        }
    
        @Override
        public void onWrite(final PageRange[] pageRanges, final ParcelFileDescriptor destination, final CancellationSignal cancellationSignal,
                            final WriteResultCallback callback) {
            for (int i = 0; i < totalpages; i++) {
                if (pageInRange(pageRanges, i)) //保证页码正确
                {
                    PageInfo newPage = new PageInfo.Builder(pageWidth,
                            pageHeight, i).create();
                    PdfDocument.Page page =
                            mPdfDocument.startPage(newPage);  //创建新页面
    
                    if (cancellationSignal.isCanceled()) {  //取消信号
                        callback.onWriteCancelled();
                        mPdfDocument.close();
                        mPdfDocument = null;
                        return;
                    }
                    drawPage(page, i);  //将内容绘制到页面Canvas上
                    mPdfDocument.finishPage(page);
                }
            }
    
            try {
                mPdfDocument.writeTo(new FileOutputStream(
                        destination.getFileDescriptor()));
            } catch (IOException e) {
                callback.onWriteFailed(e.toString());
                return;
            } finally {
                mPdfDocument.close();
                mPdfDocument = null;
            }
    
            callback.onWriteFinished(pageRanges);
        }
    
        private boolean pageInRange(PageRange[] pageRanges, int page) {
            for (int i = 0; i < pageRanges.length; i++) {
                if ((page >= pageRanges[i].getStart()) &&
                        (page <= pageRanges[i].getEnd()))
                    return true;
            }
            return false;
        }
    
        //页面绘制(渲染)
        private void drawPage(PdfDocument.Page page,int pagenumber) {
            Canvas canvas = page.getCanvas();
            if(mlist != null){
                Paint paint = new Paint();
                Bitmap bitmap = mlist.get(pagenumber);
                int bitmapWidth = bitmap.getWidth();
                int bitmapHeight = bitmap.getHeight();
                // 计算缩放比例
                float scale = (float)pageWidth/(float)bitmapWidth;
                // 取得想要缩放的matrix参数
                Matrix matrix = new Matrix();
                matrix.postScale(scale, scale);
                canvas.drawBitmap(bitmap,matrix,paint);
            }
        }
    
    }  

    .c.MainActivity.java

    package com.gatsby.printdemo;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.print.PrintAttributes;
    import android.print.PrintManager;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            onPrintPdf();
        }
    
        private void onPrintPdf() {
            PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
            PrintAttributes.Builder builder = new PrintAttributes.Builder();
            builder.setColorMode(PrintAttributes.COLOR_MODE_COLOR);
            String filePath =  "/sdcard/111.pdf";
            printManager.print("test pdf print", new MyPrintAdapter(this,filePath), builder.build());
        }
    }
    

    1.2.frameworks\base\core\java\android\print\PrintManager.java

    PrintJob 使用默认打印属性创建打印作业以打印 PrintDocumentAdapter 

    PrintJobInfo printJob = result.getParcelable(EXTRA_PRINT_JOB);
    IntentSender intent = result.getParcelable(EXTRA_PRINT_DIALOG_INTENT);

        public @NonNull PrintJob print(@NonNull String printJobName,
                @NonNull PrintDocumentAdapter documentAdapter,
                @Nullable PrintAttributes attributes) {
            if (mService == null) {
                Log.w(LOG_TAG, "Feature android.software.print not available");
                return null;
            }
            if (!(mContext instanceof Activity)) {
                throw new IllegalStateException("Can print only from an activity");
            }
            if (TextUtils.isEmpty(printJobName)) {
                throw new IllegalArgumentException("printJobName cannot be empty");
            }
            if (documentAdapter == null) {
                throw new IllegalArgumentException("documentAdapter cannot be null");
            }
            PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(
                    (Activity) mContext, documentAdapter);
            try {
                Bundle result = mService.print(printJobName, delegate,
                        attributes, mContext.getPackageName(), mAppId, mUserId);
                if (result != null) {
                    PrintJobInfo printJob = result.getParcelable(EXTRA_PRINT_JOB);
                    IntentSender intent = result.getParcelable(EXTRA_PRINT_DIALOG_INTENT);
                    if (printJob == null || intent == null) {
                        return null;
                    }
                    try {
                        mContext.startIntentSender(intent, null, 0, 0, 0);
                        return new PrintJob(printJob, this);
                    } catch (SendIntentException sie) {
                        Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
                    }
                }
            } catch (RemoteException re) {
                throw re.rethrowFromSystemServer();
            }
            return null;
        }
    

    1.3.frameworks\base\packages\PrintSpooler\AndroidManifest.xml 

    <action android:name="android.print.PRINT_DIALOG" />  intent 跳转到 PrintActivity 预览界面

            <activity
                android:name=".ui.PrintActivity"
                android:configChanges="mnc|mnc|touchscreen|navigation|screenLayout|screenSize|smallestScreenSize|orientation|locale|keyboard|keyboardHidden|fontScale|uiMode|layoutDirection|density"
                android:permission="android.permission.BIND_PRINT_SPOOLER_SERVICE"
                android:theme="@style/Theme.PrintActivity">
                <intent-filter>
                    <action android:name="android.print.PRINT_DIALOG" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:scheme="printjob" android:pathPattern="*" />
                </intent-filter>
            </activity>
    

     二.打印预览界面

     2.1.设备列表选项框 spinner

        <!-- Destination -->
    
        <FrameLayout
            android:id="@+id/static_content"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:paddingStart="8dip"
            android:layout_marginEnd="16dp"
            android:elevation="@dimen/preview_controls_elevation"
            android:background="?android:attr/colorPrimary">
    
            <Spinner
                android:id="@+id/destination_spinner"
                android:layout_width="wrap_content"
                android:minWidth="@dimen/preview_destination_spinner_width"
                android:layout_height="wrap_content"
                android:layout_marginTop="4dip"
                android:dropDownWidth="wrap_content"
                android:minHeight="?android:attr/listPreferredItemHeightSmall">
            </Spinner>
    
        </FrameLayout>
    

    2.2.加载布局 为Spinner提供Adapter显示加载数据  DataSetObserver register 注册观察者

    private void bindUi() { 
    
    …………………………
    
            // Destination.
            mPrintersObserver = new PrintersObserver();
            mDestinationSpinnerAdapter.registerDataSetObserver(mPrintersObserver);
            mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
            mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
            mDestinationSpinner.setOnItemSelectedListener(itemSelectedListener);
    

    2.3.DestinationAdapter 

        private final class DestinationAdapter extends BaseAdapter
                implements PrinterRegistry.OnPrintersChangeListener {
            private final List<PrinterHolder> mPrinterHolders = new ArrayList<>();
    
            private final PrinterHolder mFakePdfPrinterHolder;
    
            private boolean mHistoricalPrintersLoaded;
    
            /**
             * Has the {@link #mDestinationSpinner} ever used a view from printer_dropdown_prompt
             */
            private boolean hadPromptView;
    
            public DestinationAdapter() {
                mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();
                if (mHistoricalPrintersLoaded) {
                    addPrinters(mPrinterHolders, mPrinterRegistry.getPrinters());
                }
                mPrinterRegistry.setOnPrintersChangeListener(this);
                mFakePdfPrinterHolder = new PrinterHolder(createFakePdfPrinter());
            }
    
            public PrinterInfo getPdfPrinter() {
                return mFakePdfPrinterHolder.printer;
            }
    
            public int getPrinterIndex(PrinterId printerId) {
                for (int i = 0; i < getCount(); i++) {
                    PrinterHolder printerHolder = (PrinterHolder) getItem(i);
                    if (printerHolder != null && !printerHolder.removed
                            && printerHolder.printer.getId().equals(printerId)) {
                        return i;
                    }
                }
                return AdapterView.INVALID_POSITION;
            }
    
            public void ensurePrinterInVisibleAdapterPosition(PrinterInfo printer) {
                final int printerCount = mPrinterHolders.size();
                boolean isKnownPrinter = false;
                for (int i = 0; i < printerCount; i++) {
                    PrinterHolder printerHolder = mPrinterHolders.get(i);
    
                    if (printerHolder.printer.getId().equals(printer.getId())) {
                        isKnownPrinter = true;
    
                        // If already in the list - do nothing.
                        if (i < getCount() - 2) {
                            break;
                        }
                        // Else replace the last one (two items are not printers).
                        final int lastPrinterIndex = getCount() - 3;
                        mPrinterHolders.set(i, mPrinterHolders.get(lastPrinterIndex));
                        mPrinterHolders.set(lastPrinterIndex, printerHolder);
                        break;
                    }
                }
    
                if (!isKnownPrinter) {
                    PrinterHolder printerHolder = new PrinterHolder(printer);
                    printerHolder.removed = true;
    
                    mPrinterHolders.add(Math.max(0, getCount() - 3), printerHolder);
                }
    
                // Force reload to adjust selection in PrintersObserver.onChanged()
                notifyDataSetChanged();
            } 

    2.4.生成的列表 添加或者修改数据 notifyDataSetChanged()可以在修改适配器绑定的数据后 不用重新刷新Activity 通知Activity更新Spinner

    onPrintersChanged 

            @Override
            public void onPrintersChanged(List<PrinterInfo> printers) {
                // We rearrange the printers if the user selects a printer
                // not shown in the initial short list. Therefore, we have
                // to keep the printer order.
    
                // Check if historical printers are loaded as this adapter is open
                // for busyness only if they are. This member is updated here and
                // when the adapter is created because the historical printers may
                // be loaded before or after the adapter is created.
                mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();
    
                // No old printers - do not bother keeping their position.
                if (mPrinterHolders.isEmpty()) {
                    addPrinters(mPrinterHolders, printers);
                    notifyDataSetChanged();
                    return;
                }
    
                // Add the new printers to a map.
                ArrayMap<PrinterId, PrinterInfo> newPrintersMap = new ArrayMap<>();
                final int printerCount = printers.size();
                for (int i = 0; i < printerCount; i++) {
                    PrinterInfo printer = printers.get(i);
                    newPrintersMap.put(printer.getId(), printer);
                }
    
                List<PrinterHolder> newPrinterHolders = new ArrayList<>();
    
                // Update printers we already have which are either updated or removed.
                // We do not remove the currently selected printer.
                final int oldPrinterCount = mPrinterHolders.size();
                for (int i = 0; i < oldPrinterCount; i++) {
                    PrinterHolder printerHolder = mPrinterHolders.get(i);
                    PrinterId oldPrinterId = printerHolder.printer.getId();
                    PrinterInfo updatedPrinter = newPrintersMap.remove(oldPrinterId);
    
                    if (updatedPrinter != null) {
                        printerHolder.printer = updatedPrinter;
                        printerHolder.removed = false;
                        onPrinterAvailable(printerHolder.printer);
                        newPrinterHolders.add(printerHolder);
                    } else if (mCurrentPrinter != null && mCurrentPrinter.getId().equals(oldPrinterId)){
                        printerHolder.removed = true;
                        onPrinterUnavailable(printerHolder.printer);
                        newPrinterHolders.add(printerHolder);
                    }
                }
    
                // Add the rest of the new printers, i.e. what is left.
                addPrinters(newPrinterHolders, newPrintersMap.values());
    
                mPrinterHolders.clear();
                mPrinterHolders.addAll(newPrinterHolders);
    
                notifyDataSetChanged();
            }
    

    // Add the rest of the new printers, i.e. what is left.   添加剩下的新打印机,即剩余的打印机

            private void addPrinters(List<PrinterHolder> list, Collection<PrinterInfo> printers) {
                for (PrinterInfo printer : printers) {
                    PrinterHolder printerHolder = new PrinterHolder(printer);
                    list.add(printerHolder);
                }
            }

    判断是否存在有 HP打印机的设备 打印状态是否就绪

    STATUS_BUSY、STATUS_IDLE、STATUS_UNAVAILABLE三种状态,只有打印机处于STATUS_IDLE时,系统才允许使用该打印机

    			//printer_flag  				
            	for (int i = 0;i < printers.size(); i++) {
    				Log.d("gatsby", "onPrintersChanged i->" + i + " printers ->" + printers.get(i).toString() );				
    				PrinterInfo xh_printer = printers.get(i);															
    				if(xh_printer.getName().startsWith("HP") && xh_printer.getStatus() == PrinterInfo.STATUS_IDLE ){
    				  printer_flag = true;
    				}	
            	}

    2.5.onLoadFinished  创建的加载器已经完成其加载过程后被调用  mDestinationSpinnerAdapter.notifyDataSetChanged();

        @Override
        public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
                List<PrintServiceInfo> services) {
            ComponentName newAdvancedPrintOptionsActivity = null;
            if (mCurrentPrinter != null && services != null) {
                final int numServices = services.size();
                for (int i = 0; i < numServices; i++) {
                    PrintServiceInfo service = services.get(i);
    
                    if (service.getComponentName().equals(mCurrentPrinter.getId().getServiceName())) {
                        String advancedOptionsActivityName = service.getAdvancedOptionsActivityName();
    
                        if (!TextUtils.isEmpty(advancedOptionsActivityName)) {
                            newAdvancedPrintOptionsActivity = new ComponentName(
                                    service.getComponentName().getPackageName(),
                                    advancedOptionsActivityName);
    
                            break;
                        }
                    }
                }
            }
    
            if (!Objects.equals(newAdvancedPrintOptionsActivity, mAdvancedPrintOptionsActivity)) {
                mAdvancedPrintOptionsActivity = newAdvancedPrintOptionsActivity;
                updateOptionsUi();
            }
    
            boolean newArePrintServicesEnabled = services != null && !services.isEmpty();
            if (mArePrintServicesEnabled != newArePrintServicesEnabled) {
                mArePrintServicesEnabled = newArePrintServicesEnabled;
    
                // Reload mDestinationSpinnerAdapter as mArePrintServicesEnabled changed and the adapter
                // reads that in DestinationAdapter#getMoreItemTitle
                if (mDestinationSpinnerAdapter != null) {
                    mDestinationSpinnerAdapter.notifyDataSetChanged();
                }
            }
        } 

    2.6.onChanged在数据变化之后 默认第一个打印机设备 mDestinationSpinner.setSelection  并且更新设备属性 updateOptionsUi

    第一次是默认 保存为PDF

    			Log.d("gatsby","PrintersObserver printer_flag -> "+printer_flag);
    			Log.d("gatsby","PrintersObserver getSelectedItem-> "+mDestinationSpinner.getSelectedItem().toString());
    			Log.d("gatsby","PrintersObserver printerHolder-> "+printerHolder.toString());
                if (mDestinationSpinner.getSelectedItem() != printerHolder) {
    				Log.d("gatsby","PrintersObserver setSelection->"+
    				       mDestinationSpinnerAdapter.getPrinterIndex(newPrinterState.getId()));
                    mDestinationSpinner.setSelection(
                            mDestinationSpinnerAdapter.getPrinterIndex(newPrinterState.getId()));
                }
    
    
    12-16 16:51:20.421  1172  1172 D gatsby  : PrintersObserver onChanged->false
    12-16 16:51:20.422  1172  1172 D gatsby  : PrintersObserver getSelectedItem->com.android.printspooler.ui.PrintActivity$PrinterHolder@d3279cf
    12-16 16:51:20.422  1172  1172 D gatsby  : PrintersObserver printerHolder->com.android.printspooler.ui.PrintActivity$PrinterHolder@4b51f5c
    12-16 16:51:20.422  1172  1172 D gatsby  : PrintersObserver setSelection->1
    12-16 16:51:20.422  1172  1172 D gatsby  : onPrintersChanged i->0 printers ->PrinterInfo{id=PrinterId{serviceName=com.hp.android.printservice/com.hp.android.printservice.ServiceAndroidPrint, localId=net:/hpb0227a546f62.local.-HPB0227A546F62%20(HP%20Color%20Laser%20150)/HPB0227A546F62.local.}, name=HPB0227A546F62 (HP Color Laser 150), status=1, description=192.168.1.103, capabilities=null, iconResId=2131623939, hasCustomPrinterIcon=false, customPrinterIconGen=0, infoIntent=PendingIntent{dd49265: android.os.BinderProxy@73b4b3a}"}
    12-16 16:51:20.422  1172  1172 D gatsby  : onPrintersChanged i->1 printers ->PrinterInfo{id=PrinterId{serviceName=com.hp.android.printservice/com.hp.android.printservice.ServiceAndroidPrint, localId=/dev/hpusb/CNB3P59KWG}, name=USB:HP Color Laser 150, status=3, description=USB, capabilities=null, iconResId=0, hasCustomPrinterIcon=false, customPrinterIconGen=0, infoIntent=null"}
    12-16 16:51:20.422  1172  1172 D gatsby  : PrintersObserver onChanged->true
    12-16 16:51:20.422  1172  1172 D gatsby  : PrintersObserver getSelectedItem->com.android.printspooler.ui.PrintActivity$PrinterHolder@4b51f5c
    12-16 16:51:20.422  1172  1172 D gatsby  : PrintersObserver printerHolder->com.android.printspooler.ui.PrintActivity$PrinterHolder@4b51f5c
    12-16 16:51:24.893  1172  1172 D gatsby  : DestinationSpinnerSelection confirmPrint will print

    mDestinationSpinnerAdapter  数据的观察者

        private final class PrintersObserver extends DataSetObserver {
            @Override
            public void onChanged() {
                PrinterInfo oldPrinterState = mCurrentPrinter;
                if (oldPrinterState == null) {
                    return;
                }
    
                PrinterHolder printerHolder = mDestinationSpinnerAdapter.getPrinterHolder(
                        oldPrinterState.getId());
                PrinterInfo newPrinterState = printerHolder.printer;
    
                if (printerHolder.removed) {
                    onPrinterUnavailable(newPrinterState);
                }
    
                if (mDestinationSpinner.getSelectedItem() != printerHolder) {
                    mDestinationSpinner.setSelection(
                            mDestinationSpinnerAdapter.getPrinterIndex(newPrinterState.getId()));
                }
    ………………………………………………
                if (capabChanged && hasCapab) {
                    updatePrintAttributesFromCapabilities(newCapab);
                }
    ………………………………………………
                // Force a reload of the enabled print services to update mAdvancedPrintOptionsActivity
                // in onLoadFinished();
                getLoaderManager().getLoader(LOADER_ID_ENABLED_PRINT_SERVICES).forceLoad();
    
                updateOptionsUi();
                updateSummary();
            }

     updatePrintAttributesFromCapabilities  传入打印参数

        private void updatePrintAttributesFromCapabilities(PrinterCapabilitiesInfo capabilities) {
            boolean clearRanges = false;
            PrintAttributes defaults = capabilities.getDefaults();
    
            // Sort the media sizes based on the current locale.
            List<MediaSize> sortedMediaSizes = new ArrayList<>(capabilities.getMediaSizes());
            Collections.sort(sortedMediaSizes, mMediaSizeComparator);
    
            PrintAttributes attributes = mPrintJob.getAttributes();
    
            // Media size.
            MediaSize currMediaSize = attributes.getMediaSize();
            if (currMediaSize == null) {
                clearRanges = true;
                attributes.setMediaSize(defaults.getMediaSize());
            } 
    ……………………………………
    

      三.无预览打印

    3.1.直接打印 无预览打印页界面面 a.只允许惠普打印机  b.吐司提示 打印机 即将打印   c.打印过程中关闭触摸、鼠标  若离众生苦 难悟人间道

    解决思路:1.透明化预览界面  2.spinner 默认选择打印型号

    --- a/frameworks/base/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
    +++ b/frameworks/base/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
    @@ -84,6 +84,9 @@ import android.widget.ImageView;
     import android.widget.Spinner;
     import android.widget.TextView;
     
    +import android.view.WindowManager;
    +import android.os.SystemProperties;
    +
     import android.widget.Toast;
     import com.android.internal.logging.MetricsLogger;
     import com.android.printspooler.R;
    @@ -239,12 +242,17 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
     
         /** Is doFinish() already in progress */
         private boolean mIsFinishing;
    +	
    +	private PrinterInfo xh_printer;	
    +	private boolean printer_flag = false;
    +	private boolean printer_status = false;
    +	private int xh_printer_id;	
     
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
     
    -        setTitle(R.string.print_dialog);
    +        //setTitle(R.string.print_dialog);
     
             Bundle extras = getIntent().getExtras();
     
    @@ -347,6 +355,13 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
             ensurePreviewUiShown();
     
             setState(STATE_CONFIGURING);
    +		
    +		SystemProperties.set("persist.sys.UsbMouse","1");
    +		
    +		WindowManager.LayoutParams lp = getWindow().getAttributes(); 
    +		lp.alpha = 0f; 
    +		getWindow().setAttributes(lp);	
    +		
         }
     
         @Override
    @@ -636,7 +651,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
             if (mPrintedDocument != null) {
                 mPrintedDocument.cancel(true);
             }
    -
    +		Log.d("gatsby","PrintActivity onDestroy ");
             doFinish();
     
             super.onDestroy();
    @@ -1256,7 +1271,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
             mCopiesEditText.setSelection(mCopiesEditText.getText().length());
             mCopiesEditText.addTextChangedListener(new EditTextWatcher());
     
    -        // Destination.
    +        // Destination. Gatsby Destination Spinner
             mPrintersObserver = new PrintersObserver();
             mDestinationSpinnerAdapter.registerDataSetObserver(mPrintersObserver);
             mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
    @@ -1346,8 +1361,35 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                     }
                 });
             }
    +		
    +		DestinationSpinnerSelection();
         }
     
    +		private void DestinationSpinnerSelection() {
    +				        				
    +				new Handler().postDelayed(new Runnable(){
    +				@Override
    +					public void run() {
    +																
    +						if(printer_flag){																			
    +							updateOptionsUi();																		
    +							confirmPrint();				
    +							Log.d("gatsby", "DestinationSpinnerSelection confirmPrint will print");
    +							
    +							Toast.makeText(PrintActivity.this,
    +							 		getResources().getString(R.string.print_will), Toast.LENGTH_LONG).show();						
    +						}else {							
    +							Toast.makeText(PrintActivity.this,
    +							 		getResources().getString(R.string.print_noDevice), Toast.LENGTH_LONG).show();
    +						}
    +						
    +						SystemProperties.set("persist.sys.UsbMouse","0");											
    +					} 
    +				}, 5000);	       	
    +        }
    +
    +
    +
         @Override
         public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
             return new PrintServicesLoader((PrintManager) getSystemService(Context.PRINT_SERVICE), this,
    @@ -1486,6 +1528,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                         })
                         .setNegativeButton(android.R.string.cancel, null);
     
    +			Log.d("gatsby","PrintActivity AlertDialog print_service");
    +
                 return builder.create();
             }
     
    @@ -2219,7 +2263,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                 edit.apply();
             }
         }
    -
    +	
    +	//Gatsby DestinationAdapter  Adapter Start
         private final class DestinationAdapter extends BaseAdapter
                 implements PrinterRegistry.OnPrintersChangeListener {
             private final List<PrinterHolder> mPrinterHolders = new ArrayList<>();
    @@ -2464,6 +2509,10 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                 for (int i = 0; i < printerCount; i++) {
                     PrinterInfo printer = printers.get(i);
                     newPrintersMap.put(printer.getId(), printer);
    +				//Log.d("gatsby", "onPrintersChanged i-> " + i + " printers -> " + printers.get(i).toString());
    +				if(printer.getName().startsWith("HP") && printer.getStatus() == PrinterInfo.STATUS_IDLE ){
    +				  printer_status = true;
    +				}				
                 }
     
                 List<PrinterHolder> newPrinterHolders = new ArrayList<>();
    @@ -2495,6 +2544,20 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                 mPrinterHolders.addAll(newPrinterHolders);
     
                 notifyDataSetChanged();
    +						
    +			for (int i = 0; i < getCount(); i++) {
    +				PrinterHolder xh_printerHolder = (PrinterHolder) getItem(i);
    +				if(xh_printerHolder != null ){
    +					String xh_printer_title = xh_printerHolder.printer.getName();			
    +					Log.d("gatsby","xh_printerHolder i-> "+ i +" -> "+xh_printer_title);				
    +					if(xh_printer_title.contains("(HP Color Laser 150)") && printer_status){
    +						Log.d("gatsby","printerHolder -> "+xh_printer_title+" getStatus-> "+printer_status);
    +						printer_flag = true;
    +						xh_printer_id = i;										
    +					}				
    +				}										
    +			}
    +			
             }
     
             @Override
    @@ -2538,6 +2601,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                 return false;
             }
     
    +		//gatsby addPrinters
             private void addPrinters(List<PrinterHolder> list, Collection<PrinterInfo> printers) {
                 for (PrinterInfo printer : printers) {
                     PrinterHolder printerHolder = new PrinterHolder(printer);
    @@ -2570,6 +2634,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
             }
         }
     
    +	//Gatsby DestinationAdapter  Adapter End
    +
         private final class PrintersObserver extends DataSetObserver {
             @Override
             public void onChanged() {
    @@ -2577,7 +2643,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                 if (oldPrinterState == null) {
                     return;
                 }
    -
    +			
    +			Log.d("gatsby","PrintersObserver oldPrinterState.getId()-> "+oldPrinterState.getId());
                 PrinterHolder printerHolder = mDestinationSpinnerAdapter.getPrinterHolder(
                         oldPrinterState.getId());
                 PrinterInfo newPrinterState = printerHolder.printer;
    @@ -2586,10 +2653,17 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                     onPrinterUnavailable(newPrinterState);
                 }
     
    -            if (mDestinationSpinner.getSelectedItem() != printerHolder) {
    +            /*if (mDestinationSpinner.getSelectedItem() != printerHolder) {
                     mDestinationSpinner.setSelection(
                             mDestinationSpinnerAdapter.getPrinterIndex(newPrinterState.getId()));
    -            }
    +            }*/
    +			Log.d("gatsby","PrintersObserver printer_flag -> "+printer_flag +" xh_printer_id ->"+xh_printer_id);	
    +			if (printer_flag) {				
    +				mDestinationSpinner.setSelection(xh_printer_id);							
    +            }else {
    +                mDestinationSpinner.setSelection(
    +                        mDestinationSpinnerAdapter.getPrinterIndex(newPrinterState.getId()));				
    +			}
     
                 if (oldPrinterState.equals(newPrinterState)) {
                     return;
    @@ -2673,7 +2747,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                         startSelectPrinterActivity();
                         return;
                     }
    -
    +				
    +				//gatsby  currentPrinter
                     PrinterHolder currentItem = (PrinterHolder) mDestinationSpinner.getSelectedItem();
                     PrinterInfo currentPrinter = (currentItem != null) ? currentItem.printer : null;
     
    @@ -3102,6 +3177,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                 PageRange previousRange = null;
     
                 PageRange[] printedPages = printJob.getPages();
    +			if(printedPages != null && printedPages.length != 0){
                 final int rangeCount = printedPages.length;
                 for (int i = 0; i < rangeCount; i++) {
                     PageRange range = printedPages[i];
    @@ -3130,6 +3206,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
     
                     previousRange = range;
                 }
    +			}
     
                 PageRange[] result = new PageRange[rangesToShred.size()];
                 rangesToShred.toArray(result);
    

      原始真章

    /*
     * Copyright (C) 2014 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.printspooler.ui;
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.Dialog;
    import android.app.DialogFragment;
    import android.app.Fragment;
    import android.app.FragmentTransaction;
    import android.app.LoaderManager;
    import android.content.ActivityNotFoundException;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.content.Loader;
    import android.content.ServiceConnection;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
    import android.content.pm.PackageManager;
    import android.content.pm.PackageManager.NameNotFoundException;
    import android.content.pm.ResolveInfo;
    import android.content.res.Configuration;
    import android.database.DataSetObserver;
    import android.graphics.drawable.Drawable;
    import android.net.Uri;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.ParcelFileDescriptor;
    import android.os.RemoteException;
    import android.print.IPrintDocumentAdapter;
    import android.print.PageRange;
    import android.print.PrintAttributes;
    import android.print.PrintAttributes.MediaSize;
    import android.print.PrintAttributes.Resolution;
    import android.print.PrintDocumentInfo;
    import android.print.PrintJobInfo;
    import android.print.PrintManager;
    import android.print.PrintServicesLoader;
    import android.print.PrinterCapabilitiesInfo;
    import android.print.PrinterId;
    import android.print.PrinterInfo;
    import android.printservice.PrintService;
    import android.printservice.PrintServiceInfo;
    import android.provider.DocumentsContract;
    import android.text.Editable;
    import android.text.TextUtils;
    import android.text.TextWatcher;
    import android.util.ArrayMap;
    import android.util.ArraySet;
    import android.util.Log;
    import android.util.TypedValue;
    import android.view.KeyEvent;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnFocusChangeListener;
    import android.view.ViewGroup;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemSelectedListener;
    import android.widget.ArrayAdapter;
    import android.widget.BaseAdapter;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageView;
    import android.widget.Spinner;
    import android.widget.TextView;
    
    import android.view.WindowManager;
    import android.os.SystemProperties;
    
    import android.widget.Toast;
    import com.android.internal.logging.MetricsLogger;
    import com.android.printspooler.R;
    import com.android.printspooler.model.MutexFileProvider;
    import com.android.printspooler.model.PrintSpoolerProvider;
    import com.android.printspooler.model.PrintSpoolerService;
    import com.android.printspooler.model.RemotePrintDocument;
    import com.android.printspooler.model.RemotePrintDocument.RemotePrintDocumentInfo;
    import com.android.printspooler.renderer.IPdfEditor;
    import com.android.printspooler.renderer.PdfManipulationService;
    import com.android.printspooler.util.ApprovedPrintServices;
    import com.android.printspooler.util.MediaSizeUtils;
    import com.android.printspooler.util.MediaSizeUtils.MediaSizeComparator;
    import com.android.printspooler.util.PageRangeUtils;
    import com.android.printspooler.widget.PrintContentView;
    import com.android.printspooler.widget.PrintContentView.OptionsStateChangeListener;
    import com.android.printspooler.widget.PrintContentView.OptionsStateController;
    
    import libcore.io.IoUtils;
    import libcore.io.Streams;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.List;
    import java.util.Objects;
    
    public class PrintActivity extends Activity implements RemotePrintDocument.UpdateResultCallbacks,
            PrintErrorFragment.OnActionListener, PageAdapter.ContentCallbacks,
            OptionsStateChangeListener, OptionsStateController,
            LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
        private static final String LOG_TAG = "PrintActivity";
    
        private static final boolean DEBUG = false;
    
        private static final String FRAGMENT_TAG = "FRAGMENT_TAG";
    
        private static final String HAS_PRINTED_PREF = "has_printed";
    
        private static final int LOADER_ID_ENABLED_PRINT_SERVICES = 1;
        private static final int LOADER_ID_PRINT_REGISTRY = 2;
        private static final int LOADER_ID_PRINT_REGISTRY_INT = 3;
    
        private static final int ORIENTATION_PORTRAIT = 0;
        private static final int ORIENTATION_LANDSCAPE = 1;
    
        private static final int ACTIVITY_REQUEST_CREATE_FILE = 1;
        private static final int ACTIVITY_REQUEST_SELECT_PRINTER = 2;
        private static final int ACTIVITY_REQUEST_POPULATE_ADVANCED_PRINT_OPTIONS = 3;
    
        private static final int DEST_ADAPTER_MAX_ITEM_COUNT = 9;
    
        private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
        private static final int DEST_ADAPTER_ITEM_ID_MORE = Integer.MAX_VALUE - 1;
    
        private static final int STATE_INITIALIZING = 0;
        private static final int STATE_CONFIGURING = 1;
        private static final int STATE_PRINT_CONFIRMED = 2;
        private static final int STATE_PRINT_CANCELED = 3;
        private static final int STATE_UPDATE_FAILED = 4;
        private static final int STATE_CREATE_FILE_FAILED = 5;
        private static final int STATE_PRINTER_UNAVAILABLE = 6;
        private static final int STATE_UPDATE_SLOW = 7;
        private static final int STATE_PRINT_COMPLETED = 8;
    
        private static final int UI_STATE_PREVIEW = 0;
        private static final int UI_STATE_ERROR = 1;
        private static final int UI_STATE_PROGRESS = 2;
    
        private static final int MIN_COPIES = 1;
        private static final String MIN_COPIES_STRING = String.valueOf(MIN_COPIES);
    
        private boolean mIsOptionsUiBound = false;
    
        private final PrinterAvailabilityDetector mPrinterAvailabilityDetector =
                new PrinterAvailabilityDetector();
    
        private final OnFocusChangeListener mSelectAllOnFocusListener = new SelectAllOnFocusListener();
    
        private PrintSpoolerProvider mSpoolerProvider;
    
        private PrintPreviewController mPrintPreviewController;
    
        private PrintJobInfo mPrintJob;
        private RemotePrintDocument mPrintedDocument;
        private PrinterRegistry mPrinterRegistry;
    
        private EditText mCopiesEditText;
    
        private TextView mPageRangeTitle;
        private EditText mPageRangeEditText;
    
        private Spinner mDestinationSpinner;
        private DestinationAdapter mDestinationSpinnerAdapter;
        private boolean mShowDestinationPrompt;
    
        private Spinner mMediaSizeSpinner;
        private ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
    
        private Spinner mColorModeSpinner;
        private ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;
    
        private Spinner mDuplexModeSpinner;
        private ArrayAdapter<SpinnerItem<Integer>> mDuplexModeSpinnerAdapter;
    
        private Spinner mOrientationSpinner;
        private ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;
    
        private Spinner mRangeOptionsSpinner;
    
        private PrintContentView mOptionsContent;
    
        private View mSummaryContainer;
        private TextView mSummaryCopies;
        private TextView mSummaryPaperSize;
    
        private Button mMoreOptionsButton;
    
        private ImageView mPrintButton;
    
        private ProgressMessageController mProgressMessageController;
        private MutexFileProvider mFileProvider;
    
        private MediaSizeComparator mMediaSizeComparator;
    
        private PrinterInfo mCurrentPrinter;
    
        private PageRange[] mSelectedPages;
    
        private String mCallingPackageName;
    
        private int mCurrentPageCount;
    
        private int mState = STATE_INITIALIZING;
    
        private int mUiState = UI_STATE_PREVIEW;
    
        /** Observer for changes to the printers */
        private PrintersObserver mPrintersObserver;
    
        /** Advances options activity name for current printer */
        private ComponentName mAdvancedPrintOptionsActivity;
    
        /** Whether at least one print services is enabled or not */
        private boolean mArePrintServicesEnabled;
    
        /** Is doFinish() already in progress */
        private boolean mIsFinishing;
    	
    	private PrinterInfo xh_printer;	
    	private boolean printer_flag = false;
    	private boolean printer_status = false;
    	private int xh_printer_id;	
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            //setTitle(R.string.print_dialog);
    
            Bundle extras = getIntent().getExtras();
    
            mPrintJob = extras.getParcelable(PrintManager.EXTRA_PRINT_JOB);
            if (mPrintJob == null) {
                throw new IllegalArgumentException(PrintManager.EXTRA_PRINT_JOB
                        + " cannot be null");
            }
            if (mPrintJob.getAttributes() == null) {
                mPrintJob.setAttributes(new PrintAttributes.Builder().build());
            }
    
            final IBinder adapter = extras.getBinder(PrintManager.EXTRA_PRINT_DOCUMENT_ADAPTER);
            if (adapter == null) {
                throw new IllegalArgumentException(PrintManager.EXTRA_PRINT_DOCUMENT_ADAPTER
                        + " cannot be null");
            }
    
            mCallingPackageName = extras.getString(DocumentsContract.EXTRA_PACKAGE_NAME);
    
            // This will take just a few milliseconds, so just wait to
            // bind to the local service before showing the UI.
            mSpoolerProvider = new PrintSpoolerProvider(this,
                    new Runnable() {
                @Override
                public void run() {
                    if (isFinishing() || isDestroyed()) {
                        // onPause might have not been able to cancel the job, see PrintActivity#onPause
                        // To be sure, cancel the job again. Double canceling does no harm.
                        mSpoolerProvider.getSpooler().setPrintJobState(mPrintJob.getId(),
                                PrintJobInfo.STATE_CANCELED, null);
                    } else {
                        onConnectedToPrintSpooler(adapter);
                    }
                }
            });
    
            getLoaderManager().initLoader(LOADER_ID_ENABLED_PRINT_SERVICES, null, this);
        }
    
        private void onConnectedToPrintSpooler(final IBinder documentAdapter) {
            // Now that we are bound to the print spooler service,
            // create the printer registry and wait for it to get
            // the first batch of results which will be delivered
            // after reading historical data. This should be pretty
            // fast, so just wait before showing the UI.
            mPrinterRegistry = new PrinterRegistry(PrintActivity.this, () -> {
                (new Handler(getMainLooper())).post(() -> onPrinterRegistryReady(documentAdapter));
            }, LOADER_ID_PRINT_REGISTRY, LOADER_ID_PRINT_REGISTRY_INT);
        }
    
        private void onPrinterRegistryReady(IBinder documentAdapter) {
            // Now that we are bound to the local print spooler service
            // and the printer registry loaded the historical printers
            // we can show the UI without flickering.
            setContentView(R.layout.print_activity);
    
            try {
                mFileProvider = new MutexFileProvider(
                        PrintSpoolerService.generateFileForPrintJob(
                                PrintActivity.this, mPrintJob.getId()));
            } catch (IOException ioe) {
                // At this point we cannot recover, so just take it down.
                throw new IllegalStateException("Cannot create print job file", ioe);
            }
    
            mPrintPreviewController = new PrintPreviewController(PrintActivity.this,
                    mFileProvider);
            mPrintedDocument = new RemotePrintDocument(PrintActivity.this,
                    IPrintDocumentAdapter.Stub.asInterface(documentAdapter),
                    mFileProvider, new RemotePrintDocument.RemoteAdapterDeathObserver() {
                @Override
                public void onDied() {
                    Log.w(LOG_TAG, "Printing app died unexpectedly");
    
                    // If we are finishing or we are in a state that we do not need any
                    // data from the printing app, then no need to finish.
                    if (isFinishing() || isDestroyed() ||
                            (isFinalState(mState) && !mPrintedDocument.isUpdating())) {
                        return;
                    }
                    setState(STATE_PRINT_CANCELED);
                    mPrintedDocument.cancel(true);
                    doFinish();
                }
            }, PrintActivity.this);
            mProgressMessageController = new ProgressMessageController(
                    PrintActivity.this);
            mMediaSizeComparator = new MediaSizeComparator(PrintActivity.this);
            mDestinationSpinnerAdapter = new DestinationAdapter();
    
            bindUi();
            updateOptionsUi();
    
            // Now show the updated UI to avoid flicker.
            mOptionsContent.setVisibility(View.VISIBLE);
            mSelectedPages = computeSelectedPages();
            mPrintedDocument.start();
    
            ensurePreviewUiShown();
    
            setState(STATE_CONFIGURING);
    		
    		SystemProperties.set("persist.sys.UsbMouse","1");
    		
    		WindowManager.LayoutParams lp = getWindow().getAttributes(); 
    		lp.alpha = 0f; 
    		getWindow().setAttributes(lp);	
    		
        }
    
        @Override
        public void onStart() {
            super.onStart();
            if (mPrinterRegistry != null && mCurrentPrinter != null) {
                mPrinterRegistry.setTrackedPrinter(mCurrentPrinter.getId());
            }
            MetricsLogger.count(this, "print_preview", 1);
        }
    
        @Override
        public void onPause() {
            PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
    
            if (mState == STATE_INITIALIZING) {
                if (isFinishing()) {
                    if (spooler != null) {
                        spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_CANCELED, null);
                    }
                }
                super.onPause();
                return;
            }
    
            if (isFinishing()) {
                spooler.updatePrintJobUserConfigurableOptionsNoPersistence(mPrintJob);
    
                switch (mState) {
                    case STATE_PRINT_COMPLETED: {
                        if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
                            spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_COMPLETED,
                                    null);
                        } else {
                            spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_QUEUED,
                                    null);
                        }
                    } break;
    
                    case STATE_CREATE_FILE_FAILED: {
                        spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_FAILED,
                                getString(R.string.print_write_error_message));
                    } break;
    
                    default: {
                        spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_CANCELED, null);
                    } break;
                }
            }
    
            super.onPause();
        }
    
        @Override
        protected void onStop() {
            mPrinterAvailabilityDetector.cancel();
    
            if (mPrinterRegistry != null) {
                mPrinterRegistry.setTrackedPrinter(null);
            }
    
            super.onStop();
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                event.startTracking();
                return true;
            }
            return super.onKeyDown(keyCode, event);
        }
    
        @Override
        public boolean onKeyUp(int keyCode, KeyEvent event) {
            if (mState == STATE_INITIALIZING) {
                doFinish();
                return true;
            }
    
            if (mState == STATE_PRINT_CANCELED || mState == STATE_PRINT_CONFIRMED
                    || mState == STATE_PRINT_COMPLETED) {
                return true;
            }
    
            if (keyCode == KeyEvent.KEYCODE_BACK
                    && event.isTracking() && !event.isCanceled()) {
                if (mPrintPreviewController != null && mPrintPreviewController.isOptionsOpened()
                        && !hasErrors()) {
                    mPrintPreviewController.closeOptions();
                } else {
                    cancelPrint();
                }
                return true;
            }
            return super.onKeyUp(keyCode, event);
        }
    
        @Override
        public void onRequestContentUpdate() {
            if (canUpdateDocument()) {
                updateDocument(false);
            }
        }
    
        @Override
        public void onMalformedPdfFile() {
            onPrintDocumentError("Cannot print a malformed PDF file");
        }
    
        @Override
        public void onSecurePdfFile() {
            onPrintDocumentError("Cannot print a password protected PDF file");
        }
    
        private void onPrintDocumentError(String message) {
            setState(mProgressMessageController.cancel());
            ensureErrorUiShown(null, PrintErrorFragment.ACTION_RETRY);
    
            setState(STATE_UPDATE_FAILED);
    
            updateOptionsUi();
    
            mPrintedDocument.kill(message);
        }
    
        @Override
        public void onActionPerformed() {
            if (mState == STATE_UPDATE_FAILED
                    && canUpdateDocument() && updateDocument(true)) {
                ensurePreviewUiShown();
                setState(STATE_CONFIGURING);
                updateOptionsUi();
            }
        }
    
        @Override
        public void onUpdateCanceled() {
            if (DEBUG) {
                Log.i(LOG_TAG, "onUpdateCanceled()");
            }
    
            setState(mProgressMessageController.cancel());
            ensurePreviewUiShown();
    
            switch (mState) {
                case STATE_PRINT_CONFIRMED: {
                    requestCreatePdfFileOrFinish();
                } break;
    
                case STATE_CREATE_FILE_FAILED:
                case STATE_PRINT_COMPLETED:
                case STATE_PRINT_CANCELED: {
                    doFinish();
                } break;
            }
        }
    
        @Override
        public void onUpdateCompleted(RemotePrintDocumentInfo document) {
            if (DEBUG) {
                Log.i(LOG_TAG, "onUpdateCompleted()");
            }
    
            setState(mProgressMessageController.cancel());
            ensurePreviewUiShown();
    
            // Update the print job with the info for the written document. The page
            // count we get from the remote document is the pages in the document from
            // the app perspective but the print job should contain the page count from
            // print service perspective which is the pages in the written PDF not the
            // pages in the printed document.
            PrintDocumentInfo info = document.info;
            if (info != null) {
                final int pageCount = PageRangeUtils.getNormalizedPageCount(document.writtenPages,
                        getAdjustedPageCount(info));
                PrintDocumentInfo adjustedInfo = new PrintDocumentInfo.Builder(info.getName())
                        .setContentType(info.getContentType())
                        .setPageCount(pageCount)
                        .build();
    
                File file = mFileProvider.acquireFile(null);
                try {
                    adjustedInfo.setDataSize(file.length());
                } finally {
                    mFileProvider.releaseFile();
                }
    
                mPrintJob.setDocumentInfo(adjustedInfo);
                mPrintJob.setPages(document.printedPages);
            }
    
            switch (mState) {
                case STATE_PRINT_CONFIRMED: {
                    requestCreatePdfFileOrFinish();
                } break;
    
                case STATE_CREATE_FILE_FAILED:
                case STATE_PRINT_COMPLETED:
                case STATE_PRINT_CANCELED: {
                    updateOptionsUi();
    
                    doFinish();
                } break;
    
                default: {
                    updatePrintPreviewController(document.changed);
    
                    setState(STATE_CONFIGURING);
                    updateOptionsUi();
                } break;
            }
        }
    
        @Override
        public void onUpdateFailed(CharSequence error) {
            if (DEBUG) {
                Log.i(LOG_TAG, "onUpdateFailed()");
            }
    
            setState(mProgressMessageController.cancel());
            ensureErrorUiShown(error, PrintErrorFragment.ACTION_RETRY);
    
            if (mState == STATE_CREATE_FILE_FAILED
                    || mState == STATE_PRINT_COMPLETED
                    || mState == STATE_PRINT_CANCELED) {
                doFinish();
            }
    
            setState(STATE_UPDATE_FAILED);
    
            updateOptionsUi();
        }
    
        @Override
        public void onOptionsOpened() {
            updateSelectedPagesFromPreview();
        }
    
        @Override
        public void onOptionsClosed() {
            // Make sure the IME is not on the way of preview as
            // the user may have used it to type copies or range.
            InputMethodManager imm = getSystemService(InputMethodManager.class);
            imm.hideSoftInputFromWindow(mDestinationSpinner.getWindowToken(), 0);
        }
    
        private void updatePrintPreviewController(boolean contentUpdated) {
            // If we have not heard from the application, do nothing.
            RemotePrintDocumentInfo documentInfo = mPrintedDocument.getDocumentInfo();
            if (!documentInfo.laidout) {
                return;
            }
    
            // Update the preview controller.
            mPrintPreviewController.onContentUpdated(contentUpdated,
                    getAdjustedPageCount(documentInfo.info),
                    mPrintedDocument.getDocumentInfo().writtenPages,
                    mSelectedPages, mPrintJob.getAttributes().getMediaSize(),
                    mPrintJob.getAttributes().getMinMargins());
        }
    
    
        @Override
        public boolean canOpenOptions() {
            return true;
        }
    
        @Override
        public boolean canCloseOptions() {
            return !hasErrors();
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
    
            mMediaSizeComparator.onConfigurationChanged(newConfig);
    
            if (mPrintPreviewController != null) {
                mPrintPreviewController.onOrientationChanged();
            }
        }
    
        @Override
        protected void onDestroy() {
            if (mPrintedDocument != null) {
                mPrintedDocument.cancel(true);
            }
    		Log.d("gatsby","PrintActivity onDestroy ");
            doFinish();
    
            super.onDestroy();
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            switch (requestCode) {
                case ACTIVITY_REQUEST_CREATE_FILE: {
                    onStartCreateDocumentActivityResult(resultCode, data);
                } break;
    
                case ACTIVITY_REQUEST_SELECT_PRINTER: {
                    onSelectPrinterActivityResult(resultCode, data);
                } break;
    
                case ACTIVITY_REQUEST_POPULATE_ADVANCED_PRINT_OPTIONS: {
                    onAdvancedPrintOptionsActivityResult(resultCode, data);
                } break;
            }
        }
    
        private void startCreateDocumentActivity() {
            if (!isResumed()) {
                return;
            }
            PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
            if (info == null) {
                return;
            }
            Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
            intent.setType("application/pdf");
            intent.putExtra(Intent.EXTRA_TITLE, info.getName());
            intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, mCallingPackageName);
    
            try {
                startActivityForResult(intent, ACTIVITY_REQUEST_CREATE_FILE);
            } catch (Exception e) {
                Log.e(LOG_TAG, "Could not create file", e);
                Toast.makeText(this, getString(R.string.could_not_create_file),
                        Toast.LENGTH_SHORT).show();
                onStartCreateDocumentActivityResult(RESULT_CANCELED, null);
            }
        }
    
        private void onStartCreateDocumentActivityResult(int resultCode, Intent data) {
            if (resultCode == RESULT_OK && data != null) {
                updateOptionsUi();
                final Uri uri = data.getData();
                // Calling finish here does not invoke lifecycle callbacks but we
                // update the print job in onPause if finishing, hence post a message.
                mDestinationSpinner.post(new Runnable() {
                    @Override
                    public void run() {
                        transformDocumentAndFinish(uri);
                    }
                });
            } else if (resultCode == RESULT_CANCELED) {
                if (DEBUG) {
                    Log.i(LOG_TAG, "[state]" + STATE_CONFIGURING);
                }
    
                mState = STATE_CONFIGURING;
    
                // The previous update might have been canceled
                updateDocument(false);
    
                updateOptionsUi();
            } else {
                setState(STATE_CREATE_FILE_FAILED);
                updateOptionsUi();
                // Calling finish here does not invoke lifecycle callbacks but we
                // update the print job in onPause if finishing, hence post a message.
                mDestinationSpinner.post(new Runnable() {
                    @Override
                    public void run() {
                        doFinish();
                    }
                });
            }
        }
    
        private void startSelectPrinterActivity() {
            Intent intent = new Intent(this, SelectPrinterActivity.class);
            startActivityForResult(intent, ACTIVITY_REQUEST_SELECT_PRINTER);
        }
    
        private void onSelectPrinterActivityResult(int resultCode, Intent data) {
            if (resultCode == RESULT_OK && data != null) {
                PrinterInfo printerInfo = data.getParcelableExtra(
                        SelectPrinterActivity.INTENT_EXTRA_PRINTER);
                if (printerInfo != null) {
                    mCurrentPrinter = printerInfo;
                    mPrintJob.setPrinterId(printerInfo.getId());
                    mPrintJob.setPrinterName(printerInfo.getName());
    
                    mDestinationSpinnerAdapter.ensurePrinterInVisibleAdapterPosition(printerInfo);
                }
            }
    
            if (mCurrentPrinter != null) {
                // Trigger PrintersObserver.onChanged() to adjust selection back to current printer
                mDestinationSpinnerAdapter.notifyDataSetChanged();
            }
        }
    
        private void startAdvancedPrintOptionsActivity(PrinterInfo printer) {
            if (mAdvancedPrintOptionsActivity == null) {
                return;
            }
    
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.setComponent(mAdvancedPrintOptionsActivity);
    
            List<ResolveInfo> resolvedActivities = getPackageManager()
                    .queryIntentActivities(intent, 0);
            if (resolvedActivities.isEmpty()) {
                return;
            }
    
            // The activity is a component name, therefore it is one or none.
            if (resolvedActivities.get(0).activityInfo.exported) {
                PrintJobInfo.Builder printJobBuilder = new PrintJobInfo.Builder(mPrintJob);
                printJobBuilder.setPages(mSelectedPages);
    
                intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO, printJobBuilder.build());
                intent.putExtra(PrintService.EXTRA_PRINTER_INFO, printer);
                intent.putExtra(PrintService.EXTRA_PRINT_DOCUMENT_INFO,
                        mPrintedDocument.getDocumentInfo().info);
    
                // This is external activity and may not be there.
                try {
                    startActivityForResult(intent, ACTIVITY_REQUEST_POPULATE_ADVANCED_PRINT_OPTIONS);
                } catch (ActivityNotFoundException anfe) {
                    Log.e(LOG_TAG, "Error starting activity for intent: " + intent, anfe);
                }
            }
        }
    
        private void onAdvancedPrintOptionsActivityResult(int resultCode, Intent data) {
            if (resultCode != RESULT_OK || data == null) {
                return;
            }
    
            PrintJobInfo printJobInfo = data.getParcelableExtra(PrintService.EXTRA_PRINT_JOB_INFO);
    
            if (printJobInfo == null) {
                return;
            }
    
            // Take the advanced options without interpretation.
            mPrintJob.setAdvancedOptions(printJobInfo.getAdvancedOptions());
    
            if (printJobInfo.getCopies() < 1) {
                Log.w(LOG_TAG, "Cannot apply return value from advanced options activity. Copies " +
                        "must be 1 or more. Actual value is: " + printJobInfo.getCopies() + ". " +
                        "Ignoring.");
            } else {
                mCopiesEditText.setText(String.valueOf(printJobInfo.getCopies()));
                mPrintJob.setCopies(printJobInfo.getCopies());
            }
    
            PrintAttributes currAttributes = mPrintJob.getAttributes();
            PrintAttributes newAttributes = printJobInfo.getAttributes();
    
            if (newAttributes != null) {
                // Take the media size only if the current printer supports is.
                MediaSize oldMediaSize = currAttributes.getMediaSize();
                MediaSize newMediaSize = newAttributes.getMediaSize();
                if (newMediaSize != null && !oldMediaSize.equals(newMediaSize)) {
                    final int mediaSizeCount = mMediaSizeSpinnerAdapter.getCount();
                    MediaSize newMediaSizePortrait = newAttributes.getMediaSize().asPortrait();
                    for (int i = 0; i < mediaSizeCount; i++) {
                        MediaSize supportedSizePortrait = mMediaSizeSpinnerAdapter.getItem(i)
                                .value.asPortrait();
                        if (supportedSizePortrait.equals(newMediaSizePortrait)) {
                            currAttributes.setMediaSize(newMediaSize);
                            mMediaSizeSpinner.setSelection(i);
                            if (currAttributes.getMediaSize().isPortrait()) {
                                if (mOrientationSpinner.getSelectedItemPosition() != 0) {
                                    mOrientationSpinner.setSelection(0);
                                }
                            } else {
                                if (mOrientationSpinner.getSelectedItemPosition() != 1) {
                                    mOrientationSpinner.setSelection(1);
                                }
                            }
                            break;
                        }
                    }
                }
    
                // Take the resolution only if the current printer supports is.
                Resolution oldResolution = currAttributes.getResolution();
                Resolution newResolution = newAttributes.getResolution();
                if (!oldResolution.equals(newResolution)) {
                    PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
                    if (capabilities != null) {
                        List<Resolution> resolutions = capabilities.getResolutions();
                        final int resolutionCount = resolutions.size();
                        for (int i = 0; i < resolutionCount; i++) {
                            Resolution resolution = resolutions.get(i);
                            if (resolution.equals(newResolution)) {
                                currAttributes.setResolution(resolution);
                                break;
                            }
                        }
                    }
                }
    
                // Take the color mode only if the current printer supports it.
                final int currColorMode = currAttributes.getColorMode();
                final int newColorMode = newAttributes.getColorMode();
                if (currColorMode != newColorMode) {
                    final int colorModeCount = mColorModeSpinner.getCount();
                    for (int i = 0; i < colorModeCount; i++) {
                        final int supportedColorMode = mColorModeSpinnerAdapter.getItem(i).value;
                        if (supportedColorMode == newColorMode) {
                            currAttributes.setColorMode(newColorMode);
                            mColorModeSpinner.setSelection(i);
                            break;
                        }
                    }
                }
    
                // Take the duplex mode only if the current printer supports it.
                final int currDuplexMode = currAttributes.getDuplexMode();
                final int newDuplexMode = newAttributes.getDuplexMode();
                if (currDuplexMode != newDuplexMode) {
                    final int duplexModeCount = mDuplexModeSpinner.getCount();
                    for (int i = 0; i < duplexModeCount; i++) {
                        final int supportedDuplexMode = mDuplexModeSpinnerAdapter.getItem(i).value;
                        if (supportedDuplexMode == newDuplexMode) {
                            currAttributes.setDuplexMode(newDuplexMode);
                            mDuplexModeSpinner.setSelection(i);
                            break;
                        }
                    }
                }
            }
    
            // Handle selected page changes making sure they are in the doc.
            PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
            final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
            PageRange[] pageRanges = printJobInfo.getPages();
            if (pageRanges != null && pageCount > 0) {
                pageRanges = PageRangeUtils.normalize(pageRanges);
    
                List<PageRange> validatedList = new ArrayList<>();
                final int rangeCount = pageRanges.length;
                for (int i = 0; i < rangeCount; i++) {
                    PageRange pageRange = pageRanges[i];
                    if (pageRange.getEnd() >= pageCount) {
                        final int rangeStart = pageRange.getStart();
                        final int rangeEnd = pageCount - 1;
                        if (rangeStart <= rangeEnd) {
                            pageRange = new PageRange(rangeStart, rangeEnd);
                            validatedList.add(pageRange);
                        }
                        break;
                    }
                    validatedList.add(pageRange);
                }
    
                if (!validatedList.isEmpty()) {
                    PageRange[] validatedArray = new PageRange[validatedList.size()];
                    validatedList.toArray(validatedArray);
                    updateSelectedPages(validatedArray, pageCount);
                }
            }
    
            // Update the content if needed.
            if (canUpdateDocument()) {
                updateDocument(false);
            }
        }
    
        private void setState(int state) {
            if (isFinalState(mState)) {
                if (isFinalState(state)) {
                    if (DEBUG) {
                        Log.i(LOG_TAG, "[state]" + state);
                    }
                    mState = state;
                }
            } else {
                if (DEBUG) {
                    Log.i(LOG_TAG, "[state]" + state);
                }
                mState = state;
            }
        }
    
        private static boolean isFinalState(int state) {
            return state == STATE_PRINT_CANCELED
                    || state == STATE_PRINT_COMPLETED
                    || state == STATE_CREATE_FILE_FAILED;
        }
    
        private void updateSelectedPagesFromPreview() {
            PageRange[] selectedPages = mPrintPreviewController.getSelectedPages();
            if (!Arrays.equals(mSelectedPages, selectedPages)) {
                updateSelectedPages(selectedPages,
                        getAdjustedPageCount(mPrintedDocument.getDocumentInfo().info));
            }
        }
    
        private void updateSelectedPages(PageRange[] selectedPages, int pageInDocumentCount) {
            if (selectedPages == null || selectedPages.length <= 0) {
                return;
            }
    
            selectedPages = PageRangeUtils.normalize(selectedPages);
    
            // Handle the case where all pages are specified explicitly
            // instead of the *all pages* constant.
            if (PageRangeUtils.isAllPages(selectedPages, pageInDocumentCount)) {
                selectedPages = new PageRange[] {PageRange.ALL_PAGES};
            }
    
            if (Arrays.equals(mSelectedPages, selectedPages)) {
                return;
            }
    
            mSelectedPages = selectedPages;
            mPrintJob.setPages(selectedPages);
    
            if (Arrays.equals(selectedPages, PageRange.ALL_PAGES_ARRAY)) {
                if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
                    mRangeOptionsSpinner.setSelection(0);
                    mPageRangeEditText.setText("");
                }
            } else if (selectedPages[0].getStart() >= 0
                    && selectedPages[selectedPages.length - 1].getEnd() < pageInDocumentCount) {
                if (mRangeOptionsSpinner.getSelectedItemPosition() != 1) {
                    mRangeOptionsSpinner.setSelection(1);
                }
    
                StringBuilder builder = new StringBuilder();
                final int pageRangeCount = selectedPages.length;
                for (int i = 0; i < pageRangeCount; i++) {
                    if (builder.length() > 0) {
                        builder.append(',');
                    }
    
                    final int shownStartPage;
                    final int shownEndPage;
                    PageRange pageRange = selectedPages[i];
                    if (pageRange.equals(PageRange.ALL_PAGES)) {
                        shownStartPage = 1;
                        shownEndPage = pageInDocumentCount;
                    } else {
                        shownStartPage = pageRange.getStart() + 1;
                        shownEndPage = pageRange.getEnd() + 1;
                    }
    
                    builder.append(shownStartPage);
    
                    if (shownStartPage != shownEndPage) {
                        builder.append('-');
                        builder.append(shownEndPage);
                    }
                }
    
                mPageRangeEditText.setText(builder.toString());
            }
        }
    
        private void ensureProgressUiShown() {
            if (isFinishing() || isDestroyed()) {
                return;
            }
            if (mUiState != UI_STATE_PROGRESS) {
                mUiState = UI_STATE_PROGRESS;
                mPrintPreviewController.setUiShown(false);
                Fragment fragment = PrintProgressFragment.newInstance();
                showFragment(fragment);
            }
        }
    
        private void ensurePreviewUiShown() {
            if (isFinishing() || isDestroyed()) {
                return;
            }
            if (mUiState != UI_STATE_PREVIEW) {
                mUiState = UI_STATE_PREVIEW;
                mPrintPreviewController.setUiShown(true);
                showFragment(null);
            }
        }
    
        private void ensureErrorUiShown(CharSequence message, int action) {
            if (isFinishing() || isDestroyed()) {
                return;
            }
            if (mUiState != UI_STATE_ERROR) {
                mUiState = UI_STATE_ERROR;
                mPrintPreviewController.setUiShown(false);
                Fragment fragment = PrintErrorFragment.newInstance(message, action);
                showFragment(fragment);
            }
        }
    
        private void showFragment(Fragment newFragment) {
            FragmentTransaction transaction = getFragmentManager().beginTransaction();
            Fragment oldFragment = getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
            if (oldFragment != null) {
                transaction.remove(oldFragment);
            }
            if (newFragment != null) {
                transaction.add(R.id.embedded_content_container, newFragment, FRAGMENT_TAG);
            }
            transaction.commitAllowingStateLoss();
            getFragmentManager().executePendingTransactions();
        }
    
        private void requestCreatePdfFileOrFinish() {
            mPrintedDocument.cancel(false);
    
            if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
                startCreateDocumentActivity();
            } else {
                transformDocumentAndFinish(null);
            }
        }
    
        /**
         * Clear the selected page range and update the preview if needed.
         */
        private void clearPageRanges() {
            mRangeOptionsSpinner.setSelection(0);
            mPageRangeEditText.setError(null);
            mPageRangeEditText.setText("");
            mSelectedPages = PageRange.ALL_PAGES_ARRAY;
    
            if (!Arrays.equals(mSelectedPages, mPrintPreviewController.getSelectedPages())) {
                updatePrintPreviewController(false);
            }
        }
    
        private void updatePrintAttributesFromCapabilities(PrinterCapabilitiesInfo capabilities) {
            boolean clearRanges = false;
            PrintAttributes defaults = capabilities.getDefaults();
    
            // Sort the media sizes based on the current locale.
            List<MediaSize> sortedMediaSizes = new ArrayList<>(capabilities.getMediaSizes());
            Collections.sort(sortedMediaSizes, mMediaSizeComparator);
    
            PrintAttributes attributes = mPrintJob.getAttributes();
    
            // Media size.
            MediaSize currMediaSize = attributes.getMediaSize();
            if (currMediaSize == null) {
                clearRanges = true;
                attributes.setMediaSize(defaults.getMediaSize());
            } else {
                MediaSize newMediaSize = null;
                boolean isPortrait = currMediaSize.isPortrait();
    
                // Try to find the current media size in the capabilities as
                // it may be in a different orientation.
                MediaSize currMediaSizePortrait = currMediaSize.asPortrait();
                final int mediaSizeCount = sortedMediaSizes.size();
                for (int i = 0; i < mediaSizeCount; i++) {
                    MediaSize mediaSize = sortedMediaSizes.get(i);
                    if (currMediaSizePortrait.equals(mediaSize.asPortrait())) {
                        newMediaSize = mediaSize;
                        break;
                    }
                }
                // If we did not find the current media size fall back to default.
                if (newMediaSize == null) {
                    clearRanges = true;
                    newMediaSize = defaults.getMediaSize();
                }
    
                if (newMediaSize != null) {
                    if (isPortrait) {
                        attributes.setMediaSize(newMediaSize.asPortrait());
                    } else {
                        attributes.setMediaSize(newMediaSize.asLandscape());
                    }
                }
            }
    
            // Color mode.
            final int colorMode = attributes.getColorMode();
            if ((capabilities.getColorModes() & colorMode) == 0) {
                attributes.setColorMode(defaults.getColorMode());
            }
    
            // Duplex mode.
            final int duplexMode = attributes.getDuplexMode();
            if ((capabilities.getDuplexModes() & duplexMode) == 0) {
                attributes.setDuplexMode(defaults.getDuplexMode());
            }
    
            // Resolution
            Resolution resolution = attributes.getResolution();
            if (resolution == null || !capabilities.getResolutions().contains(resolution)) {
                attributes.setResolution(defaults.getResolution());
            }
    
            // Margins.
            if (!Objects.equals(attributes.getMinMargins(), defaults.getMinMargins())) {
                clearRanges = true;
            }
            attributes.setMinMargins(defaults.getMinMargins());
    
            if (clearRanges) {
                clearPageRanges();
            }
        }
    
        private boolean updateDocument(boolean clearLastError) {
            if (!clearLastError && mPrintedDocument.hasUpdateError()) {
                return false;
            }
    
            if (clearLastError && mPrintedDocument.hasUpdateError()) {
                mPrintedDocument.clearUpdateError();
            }
    
            final boolean preview = mState != STATE_PRINT_CONFIRMED;
            final PageRange[] pages;
            if (preview) {
                pages = mPrintPreviewController.getRequestedPages();
            } else {
                pages = mPrintPreviewController.getSelectedPages();
            }
    
            final boolean willUpdate = mPrintedDocument.update(mPrintJob.getAttributes(),
                    pages, preview);
    
            if (willUpdate && !mPrintedDocument.hasLaidOutPages()) {
                // When the update is done we update the print preview.
                mProgressMessageController.post();
                return true;
            } else if (!willUpdate) {
                // Update preview.
                updatePrintPreviewController(false);
            }
    
            return false;
        }
    
        private void addCurrentPrinterToHistory() {
            if (mCurrentPrinter != null) {
                PrinterId fakePdfPrinterId = mDestinationSpinnerAdapter.getPdfPrinter().getId();
                if (!mCurrentPrinter.getId().equals(fakePdfPrinterId)) {
                    mPrinterRegistry.addHistoricalPrinter(mCurrentPrinter);
                }
            }
        }
    
        private void cancelPrint() {
            setState(STATE_PRINT_CANCELED);
            updateOptionsUi();
            mPrintedDocument.cancel(true);
            doFinish();
        }
    
        /**
         * Update the selected pages from the text field.
         */
        private void updateSelectedPagesFromTextField() {
            PageRange[] selectedPages = computeSelectedPages();
            if (!Arrays.equals(mSelectedPages, selectedPages)) {
                mSelectedPages = selectedPages;
                // Update preview.
                updatePrintPreviewController(false);
            }
        }
    
        private void confirmPrint() {
            setState(STATE_PRINT_CONFIRMED);
    
            MetricsLogger.count(this, "print_confirmed", 1);
    
            updateOptionsUi();
            addCurrentPrinterToHistory();
            setUserPrinted();
    
            // updateSelectedPagesFromTextField migth update the preview, hence apply the preview first
            updateSelectedPagesFromPreview();
            updateSelectedPagesFromTextField();
    
            mPrintPreviewController.closeOptions();
    
            if (canUpdateDocument()) {
                updateDocument(false);
            }
    
            if (!mPrintedDocument.isUpdating()) {
                requestCreatePdfFileOrFinish();
            }
        }
    
        private void bindUi() {
            // Summary
            mSummaryContainer = findViewById(R.id.summary_content);
            mSummaryCopies = (TextView) findViewById(R.id.copies_count_summary);
            mSummaryPaperSize = (TextView) findViewById(R.id.paper_size_summary);
    
            // Options container
            mOptionsContent = (PrintContentView) findViewById(R.id.options_content);
            mOptionsContent.setOptionsStateChangeListener(this);
            mOptionsContent.setOpenOptionsController(this);
    
            OnItemSelectedListener itemSelectedListener = new MyOnItemSelectedListener();
            OnClickListener clickListener = new MyClickListener();
    
            // Copies
            mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
            mCopiesEditText.setOnFocusChangeListener(mSelectAllOnFocusListener);
            mCopiesEditText.setText(MIN_COPIES_STRING);
            mCopiesEditText.setSelection(mCopiesEditText.getText().length());
            mCopiesEditText.addTextChangedListener(new EditTextWatcher());
    
            // Destination. Gatsby Destination Spinner
            mPrintersObserver = new PrintersObserver();
            mDestinationSpinnerAdapter.registerDataSetObserver(mPrintersObserver);
            mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
            mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
            mDestinationSpinner.setOnItemSelectedListener(itemSelectedListener);
    
            // Media size.
            mMediaSizeSpinnerAdapter = new ArrayAdapter<>(
                    this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
            mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
            mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
            mMediaSizeSpinner.setOnItemSelectedListener(itemSelectedListener);
    
            // Color mode.
            mColorModeSpinnerAdapter = new ArrayAdapter<>(
                    this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
            mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
            mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
            mColorModeSpinner.setOnItemSelectedListener(itemSelectedListener);
    
            // Duplex mode.
            mDuplexModeSpinnerAdapter = new ArrayAdapter<>(
                    this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
            mDuplexModeSpinner = (Spinner) findViewById(R.id.duplex_spinner);
            mDuplexModeSpinner.setAdapter(mDuplexModeSpinnerAdapter);
            mDuplexModeSpinner.setOnItemSelectedListener(itemSelectedListener);
    
            // Orientation
            mOrientationSpinnerAdapter = new ArrayAdapter<>(
                    this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
            String[] orientationLabels = getResources().getStringArray(
                    R.array.orientation_labels);
            mOrientationSpinnerAdapter.add(new SpinnerItem<>(
                    ORIENTATION_PORTRAIT, orientationLabels[0]));
            mOrientationSpinnerAdapter.add(new SpinnerItem<>(
                    ORIENTATION_LANDSCAPE, orientationLabels[1]));
            mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
            mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
            mOrientationSpinner.setOnItemSelectedListener(itemSelectedListener);
    
            // Range options
            ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter = new ArrayAdapter<>(
                    this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
            mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
            mRangeOptionsSpinner.setAdapter(rangeOptionsSpinnerAdapter);
            mRangeOptionsSpinner.setOnItemSelectedListener(itemSelectedListener);
            updatePageRangeOptions(PrintDocumentInfo.PAGE_COUNT_UNKNOWN);
    
            // Page range
            mPageRangeTitle = (TextView) findViewById(R.id.page_range_title);
            mPageRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
            mPageRangeEditText.setVisibility(View.INVISIBLE);
            mPageRangeTitle.setVisibility(View.INVISIBLE);
            mPageRangeEditText.setOnFocusChangeListener(mSelectAllOnFocusListener);
            mPageRangeEditText.addTextChangedListener(new RangeTextWatcher());
    
            // Advanced options button.
            mMoreOptionsButton = (Button) findViewById(R.id.more_options_button);
            mMoreOptionsButton.setOnClickListener(clickListener);
    
            // Print button
            mPrintButton = (ImageView) findViewById(R.id.print_button);
            mPrintButton.setOnClickListener(clickListener);
    
            // The UI is now initialized
            mIsOptionsUiBound = true;
    
            // Special prompt instead of destination spinner for the first time the user printed
            if (!hasUserEverPrinted()) {
                mShowDestinationPrompt = true;
    
                mSummaryCopies.setEnabled(false);
                mSummaryPaperSize.setEnabled(false);
    
                mDestinationSpinner.setOnTouchListener(new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        mShowDestinationPrompt = false;
                        mSummaryCopies.setEnabled(true);
                        mSummaryPaperSize.setEnabled(true);
                        updateOptionsUi();
    
                        mDestinationSpinner.setOnTouchListener(null);
                        mDestinationSpinnerAdapter.notifyDataSetChanged();
    
                        return false;
                    }
                });
            }
    		
    		DestinationSpinnerSelection();
        }
    
    		private void DestinationSpinnerSelection() {
    				        				
    				new Handler().postDelayed(new Runnable(){
    				@Override
    					public void run() {
    																
    						if(printer_flag){																			
    							updateOptionsUi();																		
    							confirmPrint();				
    							Log.d("gatsby", "DestinationSpinnerSelection confirmPrint will print");
    							
    							Toast.makeText(PrintActivity.this,
    							 		getResources().getString(R.string.print_will), Toast.LENGTH_LONG).show();						
    						}else {							
    							Toast.makeText(PrintActivity.this,
    							 		getResources().getString(R.string.print_noDevice), Toast.LENGTH_LONG).show();
    						}
    						
    						SystemProperties.set("persist.sys.UsbMouse","0");											
    					} 
    				}, 5000);	       	
            }
    
    
    
        @Override
        public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
            return new PrintServicesLoader((PrintManager) getSystemService(Context.PRINT_SERVICE), this,
                    PrintManager.ENABLED_SERVICES);
        }
    
        @Override
        public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
                List<PrintServiceInfo> services) {
            ComponentName newAdvancedPrintOptionsActivity = null;
            if (mCurrentPrinter != null && services != null) {
                final int numServices = services.size();
                for (int i = 0; i < numServices; i++) {
                    PrintServiceInfo service = services.get(i);
    
                    if (service.getComponentName().equals(mCurrentPrinter.getId().getServiceName())) {
                        String advancedOptionsActivityName = service.getAdvancedOptionsActivityName();
    
                        if (!TextUtils.isEmpty(advancedOptionsActivityName)) {
                            newAdvancedPrintOptionsActivity = new ComponentName(
                                    service.getComponentName().getPackageName(),
                                    advancedOptionsActivityName);
    
                            break;
                        }
                    }
                }
            }
    
            if (!Objects.equals(newAdvancedPrintOptionsActivity, mAdvancedPrintOptionsActivity)) {
                mAdvancedPrintOptionsActivity = newAdvancedPrintOptionsActivity;
                updateOptionsUi();
            }
    
            boolean newArePrintServicesEnabled = services != null && !services.isEmpty();
            if (mArePrintServicesEnabled != newArePrintServicesEnabled) {
                mArePrintServicesEnabled = newArePrintServicesEnabled;
    
                // Reload mDestinationSpinnerAdapter as mArePrintServicesEnabled changed and the adapter
                // reads that in DestinationAdapter#getMoreItemTitle
                if (mDestinationSpinnerAdapter != null) {
                    mDestinationSpinnerAdapter.notifyDataSetChanged();
                }
            }
        }
    
        @Override
        public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
            if (!(isFinishing() || isDestroyed())) {
                onLoadFinished(loader, null);
            }
        }
    
        /**
         * A dialog that asks the user to approve a {@link PrintService}. This dialog is automatically
         * dismissed if the same {@link PrintService} gets approved by another
         * {@link PrintServiceApprovalDialog}.
         */
        private static final class PrintServiceApprovalDialog extends DialogFragment
                implements OnSharedPreferenceChangeListener {
            private static final String PRINTSERVICE_KEY = "PRINTSERVICE";
            private ApprovedPrintServices mApprovedServices;
    
            /**
             * Create a new {@link PrintServiceApprovalDialog} that ask the user to approve a
             * {@link PrintService}.
             *
             * @param printService The {@link ComponentName} of the service to approve
             * @return A new {@link PrintServiceApprovalDialog} that might approve the service
             */
            static PrintServiceApprovalDialog newInstance(ComponentName printService) {
                PrintServiceApprovalDialog dialog = new PrintServiceApprovalDialog();
    
                Bundle args = new Bundle();
                args.putParcelable(PRINTSERVICE_KEY, printService);
                dialog.setArguments(args);
    
                return dialog;
            }
    
            @Override
            public void onStop() {
                super.onStop();
    
                mApprovedServices.unregisterChangeListener(this);
            }
    
            @Override
            public void onStart() {
                super.onStart();
    
                ComponentName printService = getArguments().getParcelable(PRINTSERVICE_KEY);
                synchronized (ApprovedPrintServices.sLock) {
                    if (mApprovedServices.isApprovedService(printService)) {
                        dismiss();
                    } else {
                        mApprovedServices.registerChangeListenerLocked(this);
                    }
                }
            }
    
            @Override
            public Dialog onCreateDialog(Bundle savedInstanceState) {
                super.onCreateDialog(savedInstanceState);
    
                mApprovedServices = new ApprovedPrintServices(getActivity());
    
                PackageManager packageManager = getActivity().getPackageManager();
                CharSequence serviceLabel;
                try {
                    ComponentName printService = getArguments().getParcelable(PRINTSERVICE_KEY);
    
                    serviceLabel = packageManager.getApplicationInfo(printService.getPackageName(), 0)
                            .loadLabel(packageManager);
                } catch (NameNotFoundException e) {
                    serviceLabel = null;
                }
    
                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setTitle(getString(R.string.print_service_security_warning_title,
                        serviceLabel))
                        .setMessage(getString(R.string.print_service_security_warning_summary,
                                serviceLabel))
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int id) {
                                ComponentName printService =
                                        getArguments().getParcelable(PRINTSERVICE_KEY);
                                // Prevent onSharedPreferenceChanged from getting triggered
                                mApprovedServices
                                        .unregisterChangeListener(PrintServiceApprovalDialog.this);
    
                                mApprovedServices.addApprovedService(printService);
                                ((PrintActivity) getActivity()).confirmPrint();
                            }
                        })
                        .setNegativeButton(android.R.string.cancel, null);
    
    			Log.d("gatsby","PrintActivity AlertDialog print_service");
    
                return builder.create();
            }
    
            @Override
            public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
                ComponentName printService = getArguments().getParcelable(PRINTSERVICE_KEY);
    
                synchronized (ApprovedPrintServices.sLock) {
                    if (mApprovedServices.isApprovedService(printService)) {
                        dismiss();
                    }
                }
            }
        }
    
        private final class MyClickListener implements OnClickListener {
            @Override
            public void onClick(View view) {
                if (view == mPrintButton) {
                    if (mCurrentPrinter != null) {
                        if (mDestinationSpinnerAdapter.getPdfPrinter() == mCurrentPrinter) {
                            confirmPrint();
                        } else {
                            ApprovedPrintServices approvedServices =
                                    new ApprovedPrintServices(PrintActivity.this);
    
                            ComponentName printService = mCurrentPrinter.getId().getServiceName();
                            if (approvedServices.isApprovedService(printService)) {
                                confirmPrint();
                            } else {
                                PrintServiceApprovalDialog.newInstance(printService)
                                        .show(getFragmentManager(), "approve");
                            }
                        }
                    } else {
                        cancelPrint();
                    }
                } else if (view == mMoreOptionsButton) {
                    if (mPageRangeEditText.getError() == null) {
                        // The selected pages is only applied once the user leaves the text field. A click
                        // on this button, does not count as leaving.
                        updateSelectedPagesFromTextField();
                    }
    
                    if (mCurrentPrinter != null) {
                        startAdvancedPrintOptionsActivity(mCurrentPrinter);
                    }
                }
            }
        }
    
        private static boolean canPrint(PrinterInfo printer) {
            return printer.getCapabilities() != null
                    && printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE;
        }
    
        /**
         * Disable all options UI elements, beside the {@link #mDestinationSpinner}
         */
        private void disableOptionsUi() {
            mCopiesEditText.setEnabled(false);
            mCopiesEditText.setFocusable(false);
            mMediaSizeSpinner.setEnabled(false);
            mColorModeSpinner.setEnabled(false);
            mDuplexModeSpinner.setEnabled(false);
            mOrientationSpinner.setEnabled(false);
            mRangeOptionsSpinner.setEnabled(false);
            mPageRangeEditText.setEnabled(false);
            mPrintButton.setVisibility(View.GONE);
            mMoreOptionsButton.setEnabled(false);
        }
    
        void updateOptionsUi() {
            if (!mIsOptionsUiBound) {
                return;
            }
    
            // Always update the summary.
            updateSummary();
    
            if (mState == STATE_PRINT_CONFIRMED
                    || mState == STATE_PRINT_COMPLETED
                    || mState == STATE_PRINT_CANCELED
                    || mState == STATE_UPDATE_FAILED
                    || mState == STATE_CREATE_FILE_FAILED
                    || mState == STATE_PRINTER_UNAVAILABLE
                    || mState == STATE_UPDATE_SLOW) {
                if (mState != STATE_PRINTER_UNAVAILABLE) {
                    mDestinationSpinner.setEnabled(false);
                }
                disableOptionsUi();
                return;
            }
    
            // If no current printer, or it has no capabilities, or it is not
            // available, we disable all print options except the destination.
            if (mCurrentPrinter == null || !canPrint(mCurrentPrinter)) {
                disableOptionsUi();
                return;
            }
    
            PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
            PrintAttributes defaultAttributes = capabilities.getDefaults();
    
            // Destination.
            mDestinationSpinner.setEnabled(true);
    
            // Media size.
            mMediaSizeSpinner.setEnabled(true);
    
            List<MediaSize> mediaSizes = new ArrayList<>(capabilities.getMediaSizes());
            // Sort the media sizes based on the current locale.
            Collections.sort(mediaSizes, mMediaSizeComparator);
    
            PrintAttributes attributes = mPrintJob.getAttributes();
    
            // If the media sizes changed, we update the adapter and the spinner.
            boolean mediaSizesChanged = false;
            final int mediaSizeCount = mediaSizes.size();
            if (mediaSizeCount != mMediaSizeSpinnerAdapter.getCount()) {
                mediaSizesChanged = true;
            } else {
                for (int i = 0; i < mediaSizeCount; i++) {
                    if (!mediaSizes.get(i).equals(mMediaSizeSpinnerAdapter.getItem(i).value)) {
                        mediaSizesChanged = true;
                        break;
                    }
                }
            }
            if (mediaSizesChanged) {
                // Remember the old media size to try selecting it again.
                int oldMediaSizeNewIndex = AdapterView.INVALID_POSITION;
                MediaSize oldMediaSize = attributes.getMediaSize();
    
                // Rebuild the adapter data.
                mMediaSizeSpinnerAdapter.clear();
                for (int i = 0; i < mediaSizeCount; i++) {
                    MediaSize mediaSize = mediaSizes.get(i);
                    if (oldMediaSize != null
                            && mediaSize.asPortrait().equals(oldMediaSize.asPortrait())) {
                        // Update the index of the old selection.
                        oldMediaSizeNewIndex = i;
                    }
                    mMediaSizeSpinnerAdapter.add(new SpinnerItem<>(
                            mediaSize, mediaSize.getLabel(getPackageManager())));
                }
    
                if (oldMediaSizeNewIndex != AdapterView.INVALID_POSITION) {
                    // Select the old media size - nothing really changed.
                    if (mMediaSizeSpinner.getSelectedItemPosition() != oldMediaSizeNewIndex) {
                        mMediaSizeSpinner.setSelection(oldMediaSizeNewIndex);
                    }
                } else {
                    // Select the first or the default.
                    final int mediaSizeIndex = Math.max(mediaSizes.indexOf(
                            defaultAttributes.getMediaSize()), 0);
                    if (mMediaSizeSpinner.getSelectedItemPosition() != mediaSizeIndex) {
                        mMediaSizeSpinner.setSelection(mediaSizeIndex);
                    }
                    // Respect the orientation of the old selection.
                    if (oldMediaSize != null) {
                        if (oldMediaSize.isPortrait()) {
                            attributes.setMediaSize(mMediaSizeSpinnerAdapter
                                    .getItem(mediaSizeIndex).value.asPortrait());
                        } else {
                            attributes.setMediaSize(mMediaSizeSpinnerAdapter
                                    .getItem(mediaSizeIndex).value.asLandscape());
                        }
                    }
                }
            }
    
            // Color mode.
            mColorModeSpinner.setEnabled(true);
            final int colorModes = capabilities.getColorModes();
    
            // If the color modes changed, we update the adapter and the spinner.
            boolean colorModesChanged = false;
            if (Integer.bitCount(colorModes) != mColorModeSpinnerAdapter.getCount()) {
                colorModesChanged = true;
            } else {
                int remainingColorModes = colorModes;
                int adapterIndex = 0;
                while (remainingColorModes != 0) {
                    final int colorBitOffset = Integer.numberOfTrailingZeros(remainingColorModes);
                    final int colorMode = 1 << colorBitOffset;
                    remainingColorModes &= ~colorMode;
                    if (colorMode != mColorModeSpinnerAdapter.getItem(adapterIndex).value) {
                        colorModesChanged = true;
                        break;
                    }
                    adapterIndex++;
                }
            }
            if (colorModesChanged) {
                // Remember the old color mode to try selecting it again.
                int oldColorModeNewIndex = AdapterView.INVALID_POSITION;
                final int oldColorMode = attributes.getColorMode();
    
                // Rebuild the adapter data.
                mColorModeSpinnerAdapter.clear();
                String[] colorModeLabels = getResources().getStringArray(R.array.color_mode_labels);
                int remainingColorModes = colorModes;
                while (remainingColorModes != 0) {
                    final int colorBitOffset = Integer.numberOfTrailingZeros(remainingColorModes);
                    final int colorMode = 1 << colorBitOffset;
                    if (colorMode == oldColorMode) {
                        // Update the index of the old selection.
                        oldColorModeNewIndex = mColorModeSpinnerAdapter.getCount();
                    }
                    remainingColorModes &= ~colorMode;
                    mColorModeSpinnerAdapter.add(new SpinnerItem<>(colorMode,
                            colorModeLabels[colorBitOffset]));
                }
                if (oldColorModeNewIndex != AdapterView.INVALID_POSITION) {
                    // Select the old color mode - nothing really changed.
                    if (mColorModeSpinner.getSelectedItemPosition() != oldColorModeNewIndex) {
                        mColorModeSpinner.setSelection(oldColorModeNewIndex);
                    }
                } else {
                    // Select the default.
                    final int selectedColorMode = colorModes & defaultAttributes.getColorMode();
                    final int itemCount = mColorModeSpinnerAdapter.getCount();
                    for (int i = 0; i < itemCount; i++) {
                        SpinnerItem<Integer> item = mColorModeSpinnerAdapter.getItem(i);
                        if (selectedColorMode == item.value) {
                            if (mColorModeSpinner.getSelectedItemPosition() != i) {
                                mColorModeSpinner.setSelection(i);
                            }
                            attributes.setColorMode(selectedColorMode);
                            break;
                        }
                    }
                }
            }
    
            // Duplex mode.
            mDuplexModeSpinner.setEnabled(true);
            final int duplexModes = capabilities.getDuplexModes();
    
            // If the duplex modes changed, we update the adapter and the spinner.
            // Note that we use bit count +1 to account for the no duplex option.
            boolean duplexModesChanged = false;
            if (Integer.bitCount(duplexModes) != mDuplexModeSpinnerAdapter.getCount()) {
                duplexModesChanged = true;
            } else {
                int remainingDuplexModes = duplexModes;
                int adapterIndex = 0;
                while (remainingDuplexModes != 0) {
                    final int duplexBitOffset = Integer.numberOfTrailingZeros(remainingDuplexModes);
                    final int duplexMode = 1 << duplexBitOffset;
                    remainingDuplexModes &= ~duplexMode;
                    if (duplexMode != mDuplexModeSpinnerAdapter.getItem(adapterIndex).value) {
                        duplexModesChanged = true;
                        break;
                    }
                    adapterIndex++;
                }
            }
            if (duplexModesChanged) {
                // Remember the old duplex mode to try selecting it again. Also the fallback
                // is no duplexing which is always the first item in the dropdown.
                int oldDuplexModeNewIndex = AdapterView.INVALID_POSITION;
                final int oldDuplexMode = attributes.getDuplexMode();
    
                // Rebuild the adapter data.
                mDuplexModeSpinnerAdapter.clear();
                String[] duplexModeLabels = getResources().getStringArray(R.array.duplex_mode_labels);
                int remainingDuplexModes = duplexModes;
                while (remainingDuplexModes != 0) {
                    final int duplexBitOffset = Integer.numberOfTrailingZeros(remainingDuplexModes);
                    final int duplexMode = 1 << duplexBitOffset;
                    if (duplexMode == oldDuplexMode) {
                        // Update the index of the old selection.
                        oldDuplexModeNewIndex = mDuplexModeSpinnerAdapter.getCount();
                    }
                    remainingDuplexModes &= ~duplexMode;
                    mDuplexModeSpinnerAdapter.add(new SpinnerItem<>(duplexMode,
                            duplexModeLabels[duplexBitOffset]));
                }
    
                if (oldDuplexModeNewIndex != AdapterView.INVALID_POSITION) {
                    // Select the old duplex mode - nothing really changed.
                    if (mDuplexModeSpinner.getSelectedItemPosition() != oldDuplexModeNewIndex) {
                        mDuplexModeSpinner.setSelection(oldDuplexModeNewIndex);
                    }
                } else {
                    // Select the default.
                    final int selectedDuplexMode = defaultAttributes.getDuplexMode();
                    final int itemCount = mDuplexModeSpinnerAdapter.getCount();
                    for (int i = 0; i < itemCount; i++) {
                        SpinnerItem<Integer> item = mDuplexModeSpinnerAdapter.getItem(i);
                        if (selectedDuplexMode == item.value) {
                            if (mDuplexModeSpinner.getSelectedItemPosition() != i) {
                                mDuplexModeSpinner.setSelection(i);
                            }
                            attributes.setDuplexMode(selectedDuplexMode);
                            break;
                        }
                    }
                }
            }
    
            mDuplexModeSpinner.setEnabled(mDuplexModeSpinnerAdapter.getCount() > 1);
    
            // Orientation
            mOrientationSpinner.setEnabled(true);
            MediaSize mediaSize = attributes.getMediaSize();
            if (mediaSize != null) {
                if (mediaSize.isPortrait()
                        && mOrientationSpinner.getSelectedItemPosition() != 0) {
                    mOrientationSpinner.setSelection(0);
                } else if (!mediaSize.isPortrait()
                        && mOrientationSpinner.getSelectedItemPosition() != 1) {
                    mOrientationSpinner.setSelection(1);
                }
            }
    
            // Range options
            PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
            final int pageCount = getAdjustedPageCount(info);
            if (pageCount > 0) {
                if (info != null) {
                    if (pageCount == 1) {
                        mRangeOptionsSpinner.setEnabled(false);
                    } else {
                        mRangeOptionsSpinner.setEnabled(true);
                        if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
                            if (!mPageRangeEditText.isEnabled()) {
                                mPageRangeEditText.setEnabled(true);
                                mPageRangeEditText.setVisibility(View.VISIBLE);
                                mPageRangeTitle.setVisibility(View.VISIBLE);
                                mPageRangeEditText.requestFocus();
                                InputMethodManager imm = (InputMethodManager)
                                        getSystemService(Context.INPUT_METHOD_SERVICE);
                                imm.showSoftInput(mPageRangeEditText, 0);
                            }
                        } else {
                            mPageRangeEditText.setEnabled(false);
                            mPageRangeEditText.setVisibility(View.INVISIBLE);
                            mPageRangeTitle.setVisibility(View.INVISIBLE);
                        }
                    }
                } else {
                    if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
                        mRangeOptionsSpinner.setSelection(0);
                        mPageRangeEditText.setText("");
                    }
                    mRangeOptionsSpinner.setEnabled(false);
                    mPageRangeEditText.setEnabled(false);
                    mPageRangeEditText.setVisibility(View.INVISIBLE);
                    mPageRangeTitle.setVisibility(View.INVISIBLE);
                }
            }
    
            final int newPageCount = getAdjustedPageCount(info);
            if (newPageCount != mCurrentPageCount) {
                mCurrentPageCount = newPageCount;
                updatePageRangeOptions(newPageCount);
            }
    
            // Advanced print options
            if (mAdvancedPrintOptionsActivity != null) {
                mMoreOptionsButton.setVisibility(View.VISIBLE);
                mMoreOptionsButton.setEnabled(true);
            } else {
                mMoreOptionsButton.setVisibility(View.GONE);
                mMoreOptionsButton.setEnabled(false);
            }
    
            // Print
            if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
                mPrintButton.setImageResource(com.android.internal.R.drawable.ic_print);
                mPrintButton.setContentDescription(getString(R.string.print_button));
            } else {
                mPrintButton.setImageResource(R.drawable.ic_menu_savetopdf);
                mPrintButton.setContentDescription(getString(R.string.savetopdf_button));
            }
            if (!mPrintedDocument.getDocumentInfo().laidout
                    ||(mRangeOptionsSpinner.getSelectedItemPosition() == 1
                    && (TextUtils.isEmpty(mPageRangeEditText.getText()) || hasErrors()))
                    || (mRangeOptionsSpinner.getSelectedItemPosition() == 0
                    && (mPrintedDocument.getDocumentInfo() == null || hasErrors()))) {
                mPrintButton.setVisibility(View.GONE);
            } else {
                mPrintButton.setVisibility(View.VISIBLE);
            }
    
            // Copies
            if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
                mCopiesEditText.setEnabled(true);
                mCopiesEditText.setFocusableInTouchMode(true);
            } else {
                CharSequence text = mCopiesEditText.getText();
                if (TextUtils.isEmpty(text) || !MIN_COPIES_STRING.equals(text.toString())) {
                    mCopiesEditText.setText(MIN_COPIES_STRING);
                }
                mCopiesEditText.setEnabled(false);
                mCopiesEditText.setFocusable(false);
            }
            if (mCopiesEditText.getError() == null
                    && TextUtils.isEmpty(mCopiesEditText.getText())) {
                mCopiesEditText.setText(MIN_COPIES_STRING);
                mCopiesEditText.requestFocus();
            }
    
            if (mShowDestinationPrompt) {
                disableOptionsUi();
            }
        }
    
        private void updateSummary() {
            if (!mIsOptionsUiBound) {
                return;
            }
    
            CharSequence copiesText = null;
            CharSequence mediaSizeText = null;
    
            if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
                copiesText = mCopiesEditText.getText();
                mSummaryCopies.setText(copiesText);
            }
    
            final int selectedMediaIndex = mMediaSizeSpinner.getSelectedItemPosition();
            if (selectedMediaIndex >= 0) {
                SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(selectedMediaIndex);
                mediaSizeText = mediaItem.label;
                mSummaryPaperSize.setText(mediaSizeText);
            }
    
            if (!TextUtils.isEmpty(copiesText) && !TextUtils.isEmpty(mediaSizeText)) {
                String summaryText = getString(R.string.summary_template, copiesText, mediaSizeText);
                mSummaryContainer.setContentDescription(summaryText);
            }
        }
    
        private void updatePageRangeOptions(int pageCount) {
            @SuppressWarnings("unchecked")
            ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter =
                    (ArrayAdapter<SpinnerItem<Integer>>) mRangeOptionsSpinner.getAdapter();
            rangeOptionsSpinnerAdapter.clear();
    
            final int[] rangeOptionsValues = getResources().getIntArray(
                    R.array.page_options_values);
    
            String pageCountLabel = (pageCount > 0) ? String.valueOf(pageCount) : "";
            String[] rangeOptionsLabels = new String[] {
                getString(R.string.template_all_pages, pageCountLabel),
                getString(R.string.template_page_range, pageCountLabel)
            };
    
            final int rangeOptionsCount = rangeOptionsLabels.length;
            for (int i = 0; i < rangeOptionsCount; i++) {
                rangeOptionsSpinnerAdapter.add(new SpinnerItem<>(
                        rangeOptionsValues[i], rangeOptionsLabels[i]));
            }
        }
    
        private PageRange[] computeSelectedPages() {
            if (hasErrors()) {
                return null;
            }
    
            if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
                PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
                final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
    
                return PageRangeUtils.parsePageRanges(mPageRangeEditText.getText(), pageCount);
            }
    
            return PageRange.ALL_PAGES_ARRAY;
        }
    
        private int getAdjustedPageCount(PrintDocumentInfo info) {
            if (info != null) {
                final int pageCount = info.getPageCount();
                if (pageCount != PrintDocumentInfo.PAGE_COUNT_UNKNOWN) {
                    return pageCount;
                }
            }
            // If the app does not tell us how many pages are in the
            // doc we ask for all pages and use the document page count.
            return mPrintPreviewController.getFilePageCount();
        }
    
        private boolean hasErrors() {
            return (mCopiesEditText.getError() != null)
                    || (mPageRangeEditText.getVisibility() == View.VISIBLE
                    && mPageRangeEditText.getError() != null);
        }
    
        public void onPrinterAvailable(PrinterInfo printer) {
            if (mCurrentPrinter != null && mCurrentPrinter.equals(printer)) {
                setState(STATE_CONFIGURING);
                if (canUpdateDocument()) {
                    updateDocument(false);
                }
                ensurePreviewUiShown();
                updateOptionsUi();
            }
        }
    
        public void onPrinterUnavailable(PrinterInfo printer) {
            if (mCurrentPrinter.getId().equals(printer.getId())) {
                setState(STATE_PRINTER_UNAVAILABLE);
                mPrintedDocument.cancel(false);
                ensureErrorUiShown(getString(R.string.print_error_printer_unavailable),
                        PrintErrorFragment.ACTION_NONE);
                updateOptionsUi();
            }
        }
    
        private boolean canUpdateDocument() {
            if (mPrintedDocument.isDestroyed()) {
                return false;
            }
    
            if (hasErrors()) {
                return false;
            }
    
            PrintAttributes attributes = mPrintJob.getAttributes();
    
            final int colorMode = attributes.getColorMode();
            if (colorMode != PrintAttributes.COLOR_MODE_COLOR
                    && colorMode != PrintAttributes.COLOR_MODE_MONOCHROME) {
                return false;
            }
            if (attributes.getMediaSize() == null) {
                return false;
            }
            if (attributes.getMinMargins() == null) {
                return false;
            }
            if (attributes.getResolution() == null) {
                return false;
            }
    
            if (mCurrentPrinter == null) {
                return false;
            }
            PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
            if (capabilities == null) {
                return false;
            }
            if (mCurrentPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE) {
                return false;
            }
    
            return true;
        }
    
        private void transformDocumentAndFinish(final Uri writeToUri) {
            // If saving to PDF, apply the attibutes as we are acting as a print service.
            PrintAttributes attributes = mDestinationSpinnerAdapter.getPdfPrinter() == mCurrentPrinter
                    ?  mPrintJob.getAttributes() : null;
            new DocumentTransformer(this, mPrintJob, mFileProvider, attributes, new Runnable() {
                @Override
                public void run() {
                    if (writeToUri != null) {
                        mPrintedDocument.writeContent(getContentResolver(), writeToUri);
                    }
                    setState(STATE_PRINT_COMPLETED);
                    doFinish();
                }
            }).transform();
        }
    
        private void doFinish() {
            if (mPrintedDocument != null && mPrintedDocument.isUpdating()) {
                // The printedDocument will call doFinish() when the current command finishes
                return;
            }
    
            if (mIsFinishing) {
                return;
            }
    
            mIsFinishing = true;
    
            if (mPrinterRegistry != null) {
                mPrinterRegistry.setTrackedPrinter(null);
                mPrinterRegistry.setOnPrintersChangeListener(null);
            }
    
            if (mPrintersObserver != null) {
                mDestinationSpinnerAdapter.unregisterDataSetObserver(mPrintersObserver);
            }
    
            if (mSpoolerProvider != null) {
                mSpoolerProvider.destroy();
            }
    
            if (mProgressMessageController != null) {
                setState(mProgressMessageController.cancel());
            }
    
            if (mState != STATE_INITIALIZING) {
                mPrintedDocument.finish();
                mPrintedDocument.destroy();
                mPrintPreviewController.destroy(new Runnable() {
                    @Override
                    public void run() {
                        finish();
                    }
                });
            } else {
                finish();
            }
        }
    
        private final class SpinnerItem<T> {
            final T value;
            final CharSequence label;
    
            public SpinnerItem(T value, CharSequence label) {
                this.value = value;
                this.label = label;
            }
    
            @Override
            public String toString() {
                return label.toString();
            }
        }
    
        private final class PrinterAvailabilityDetector implements Runnable {
            private static final long UNAVAILABLE_TIMEOUT_MILLIS = 10000; // 10sec
    
            private boolean mPosted;
    
            private boolean mPrinterUnavailable;
    
            private PrinterInfo mPrinter;
    
            public void updatePrinter(PrinterInfo printer) {
                if (printer.equals(mDestinationSpinnerAdapter.getPdfPrinter())) {
                    return;
                }
    
                final boolean available = printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE
                        && printer.getCapabilities() != null;
                final boolean notifyIfAvailable;
    
                if (mPrinter == null || !mPrinter.getId().equals(printer.getId())) {
                    notifyIfAvailable = true;
                    unpostIfNeeded();
                    mPrinterUnavailable = false;
                    mPrinter = new PrinterInfo.Builder(printer).build();
                } else {
                    notifyIfAvailable =
                            (mPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE
                                    && printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE)
                                    || (mPrinter.getCapabilities() == null
                                    && printer.getCapabilities() != null);
                    mPrinter = printer;
                }
    
                if (available) {
                    unpostIfNeeded();
                    mPrinterUnavailable = false;
                    if (notifyIfAvailable) {
                        onPrinterAvailable(mPrinter);
                    }
                } else {
                    if (!mPrinterUnavailable) {
                        postIfNeeded();
                    }
                }
            }
    
            public void cancel() {
                unpostIfNeeded();
                mPrinterUnavailable = false;
            }
    
            private void postIfNeeded() {
                if (!mPosted) {
                    mPosted = true;
                    mDestinationSpinner.postDelayed(this, UNAVAILABLE_TIMEOUT_MILLIS);
                }
            }
    
            private void unpostIfNeeded() {
                if (mPosted) {
                    mPosted = false;
                    mDestinationSpinner.removeCallbacks(this);
                }
            }
    
            @Override
            public void run() {
                mPosted = false;
                mPrinterUnavailable = true;
                onPrinterUnavailable(mPrinter);
            }
        }
    
        private static final class PrinterHolder {
            PrinterInfo printer;
            boolean removed;
    
            public PrinterHolder(PrinterInfo printer) {
                this.printer = printer;
            }
        }
    
    
        /**
         * Check if the user has ever printed a document
         *
         * @return true iff the user has ever printed a document
         */
        private boolean hasUserEverPrinted() {
            SharedPreferences preferences = getSharedPreferences(HAS_PRINTED_PREF, MODE_PRIVATE);
    
            return preferences.getBoolean(HAS_PRINTED_PREF, false);
        }
    
        /**
         * Remember that the user printed a document
         */
        private void setUserPrinted() {
            SharedPreferences preferences = getSharedPreferences(HAS_PRINTED_PREF, MODE_PRIVATE);
    
            if (!preferences.getBoolean(HAS_PRINTED_PREF, false)) {
                SharedPreferences.Editor edit = preferences.edit();
    
                edit.putBoolean(HAS_PRINTED_PREF, true);
                edit.apply();
            }
        }
    	
    	//Gatsby DestinationAdapter  Adapter Start
        private final class DestinationAdapter extends BaseAdapter
                implements PrinterRegistry.OnPrintersChangeListener {
            private final List<PrinterHolder> mPrinterHolders = new ArrayList<>();
    
            private final PrinterHolder mFakePdfPrinterHolder;
    
            private boolean mHistoricalPrintersLoaded;
    
            /**
             * Has the {@link #mDestinationSpinner} ever used a view from printer_dropdown_prompt
             */
            private boolean hadPromptView;
    
            public DestinationAdapter() {
                mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();
                if (mHistoricalPrintersLoaded) {
                    addPrinters(mPrinterHolders, mPrinterRegistry.getPrinters());
                }
                mPrinterRegistry.setOnPrintersChangeListener(this);
                mFakePdfPrinterHolder = new PrinterHolder(createFakePdfPrinter());
            }
    
            public PrinterInfo getPdfPrinter() {
                return mFakePdfPrinterHolder.printer;
            }
    
            public int getPrinterIndex(PrinterId printerId) {
                for (int i = 0; i < getCount(); i++) {
                    PrinterHolder printerHolder = (PrinterHolder) getItem(i);
                    if (printerHolder != null && !printerHolder.removed
                            && printerHolder.printer.getId().equals(printerId)) {
                        return i;
                    }
                }
                return AdapterView.INVALID_POSITION;
            }
    
            public void ensurePrinterInVisibleAdapterPosition(PrinterInfo printer) {
                final int printerCount = mPrinterHolders.size();
                boolean isKnownPrinter = false;
                for (int i = 0; i < printerCount; i++) {
                    PrinterHolder printerHolder = mPrinterHolders.get(i);
    
                    if (printerHolder.printer.getId().equals(printer.getId())) {
                        isKnownPrinter = true;
    
                        // If already in the list - do nothing.
                        if (i < getCount() - 2) {
                            break;
                        }
                        // Else replace the last one (two items are not printers).
                        final int lastPrinterIndex = getCount() - 3;
                        mPrinterHolders.set(i, mPrinterHolders.get(lastPrinterIndex));
                        mPrinterHolders.set(lastPrinterIndex, printerHolder);
                        break;
                    }
                }
    
                if (!isKnownPrinter) {
                    PrinterHolder printerHolder = new PrinterHolder(printer);
                    printerHolder.removed = true;
    
                    mPrinterHolders.add(Math.max(0, getCount() - 3), printerHolder);
                }
    
                // Force reload to adjust selection in PrintersObserver.onChanged()
                notifyDataSetChanged();
            }
    
            @Override
            public int getCount() {
                if (mHistoricalPrintersLoaded) {
                    return Math.min(mPrinterHolders.size() + 2, DEST_ADAPTER_MAX_ITEM_COUNT);
                }
                return 0;
            }
    
            @Override
            public boolean isEnabled(int position) {
                Object item = getItem(position);
                if (item instanceof PrinterHolder) {
                    PrinterHolder printerHolder = (PrinterHolder) item;
                    return !printerHolder.removed
                            && printerHolder.printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE;
                }
                return true;
            }
    
            @Override
            public Object getItem(int position) {
                if (mPrinterHolders.isEmpty()) {
                    if (position == 0) {
                        return mFakePdfPrinterHolder;
                    }
                } else {
                    if (position < 1) {
                        return mPrinterHolders.get(position);
                    }
                    if (position == 1) {
                        return mFakePdfPrinterHolder;
                    }
                    if (position < getCount() - 1) {
                        return mPrinterHolders.get(position - 1);
                    }
                }
                return null;
            }
    
            @Override
            public long getItemId(int position) {
                if (mPrinterHolders.isEmpty()) {
                    if (position == 0) {
                        return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
                    } else if (position == 1) {
                        return DEST_ADAPTER_ITEM_ID_MORE;
                    }
                } else {
                    if (position == 1) {
                        return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
                    }
                    if (position == getCount() - 1) {
                        return DEST_ADAPTER_ITEM_ID_MORE;
                    }
                }
                return position;
            }
    
            @Override
            public View getDropDownView(int position, View convertView, ViewGroup parent) {
                View view = getView(position, convertView, parent);
                view.setEnabled(isEnabled(position));
                return view;
            }
    
            private String getMoreItemTitle() {
                if (mArePrintServicesEnabled) {
                    return getString(R.string.all_printers);
                } else {
                    return getString(R.string.print_add_printer);
                }
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                if (mShowDestinationPrompt) {
                    if (convertView == null) {
                        convertView = getLayoutInflater().inflate(
                                R.layout.printer_dropdown_prompt, parent, false);
                        hadPromptView = true;
                    }
    
                    return convertView;
                } else {
                    // We don't know if we got an recyled printer_dropdown_prompt, hence do not use it
                    if (hadPromptView || convertView == null) {
                        convertView = getLayoutInflater().inflate(
                                R.layout.printer_dropdown_item, parent, false);
                    }
                }
    
                CharSequence title = null;
                CharSequence subtitle = null;
                Drawable icon = null;
    
                if (mPrinterHolders.isEmpty()) {
                    if (position == 0 && getPdfPrinter() != null) {
                        PrinterHolder printerHolder = (PrinterHolder) getItem(position);
                        title = printerHolder.printer.getName();
                        icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf, null);
                    } else if (position == 1) {
                        title = getMoreItemTitle();
                    }
                } else {
                    if (position == 1 && getPdfPrinter() != null) {
                        PrinterHolder printerHolder = (PrinterHolder) getItem(position);
                        title = printerHolder.printer.getName();
                        icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf, null);
                    } else if (position == getCount() - 1) {
                        title = getMoreItemTitle();
                    } else {
                        PrinterHolder printerHolder = (PrinterHolder) getItem(position);
                        PrinterInfo printInfo = printerHolder.printer;
    
                        title = printInfo.getName();
                        icon = printInfo.loadIcon(PrintActivity.this);
                        subtitle = printInfo.getDescription();
                    }
                }
    
                TextView titleView = (TextView) convertView.findViewById(R.id.title);
                titleView.setText(title);
    
                TextView subtitleView = (TextView) convertView.findViewById(R.id.subtitle);
                if (!TextUtils.isEmpty(subtitle)) {
                    subtitleView.setText(subtitle);
                    subtitleView.setVisibility(View.VISIBLE);
                } else {
                    subtitleView.setText(null);
                    subtitleView.setVisibility(View.GONE);
                }
    
                ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
                if (icon != null) {
                    iconView.setVisibility(View.VISIBLE);
                    if (!isEnabled(position)) {
                        icon.mutate();
    
                        TypedValue value = new TypedValue();
                        getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true);
                        icon.setAlpha((int)(value.getFloat() * 255));
                    }
                    iconView.setImageDrawable(icon);
                } else {
                    iconView.setVisibility(View.INVISIBLE);
                }
    
                return convertView;
            }
    
            @Override
            public void onPrintersChanged(List<PrinterInfo> printers) {
                // We rearrange the printers if the user selects a printer
                // not shown in the initial short list. Therefore, we have
                // to keep the printer order.
    
                // Check if historical printers are loaded as this adapter is open
                // for busyness only if they are. This member is updated here and
                // when the adapter is created because the historical printers may
                // be loaded before or after the adapter is created.
                mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();
    
                // No old printers - do not bother keeping their position.
                if (mPrinterHolders.isEmpty()) {
                    addPrinters(mPrinterHolders, printers);
                    notifyDataSetChanged();
                    return;
                }
    
                // Add the new printers to a map.
                ArrayMap<PrinterId, PrinterInfo> newPrintersMap = new ArrayMap<>();
                final int printerCount = printers.size();
                for (int i = 0; i < printerCount; i++) {
                    PrinterInfo printer = printers.get(i);
                    newPrintersMap.put(printer.getId(), printer);
    				//Log.d("gatsby", "onPrintersChanged i-> " + i + " printers -> " + printers.get(i).toString());
    				if(printer.getName().startsWith("HP") && printer.getStatus() == PrinterInfo.STATUS_IDLE ){
    				  printer_status = true;
    				}				
                }
    
                List<PrinterHolder> newPrinterHolders = new ArrayList<>();
    
                // Update printers we already have which are either updated or removed.
                // We do not remove the currently selected printer.
                final int oldPrinterCount = mPrinterHolders.size();
                for (int i = 0; i < oldPrinterCount; i++) {
                    PrinterHolder printerHolder = mPrinterHolders.get(i);
                    PrinterId oldPrinterId = printerHolder.printer.getId();
                    PrinterInfo updatedPrinter = newPrintersMap.remove(oldPrinterId);
    
                    if (updatedPrinter != null) {
                        printerHolder.printer = updatedPrinter;
                        printerHolder.removed = false;
                        onPrinterAvailable(printerHolder.printer);
                        newPrinterHolders.add(printerHolder);
                    } else if (mCurrentPrinter != null && mCurrentPrinter.getId().equals(oldPrinterId)){
                        printerHolder.removed = true;
                        onPrinterUnavailable(printerHolder.printer);
                        newPrinterHolders.add(printerHolder);
                    }
                }
    
                // Add the rest of the new printers, i.e. what is left.
                addPrinters(newPrinterHolders, newPrintersMap.values());
    
                mPrinterHolders.clear();
                mPrinterHolders.addAll(newPrinterHolders);
    
                notifyDataSetChanged();
    						
    			for (int i = 0; i < getCount(); i++) {
    				PrinterHolder xh_printerHolder = (PrinterHolder) getItem(i);
    				if(xh_printerHolder != null ){
    					String xh_printer_title = xh_printerHolder.printer.getName();			
    					Log.d("gatsby","xh_printerHolder i-> "+ i +" -> "+xh_printer_title);				
    					if(xh_printer_title.contains("(HP Color Laser 150)") && printer_status){
    						Log.d("gatsby","printerHolder -> "+xh_printer_title+" getStatus-> "+printer_status);
    						printer_flag = true;
    						xh_printer_id = i;										
    					}				
    				}										
    			}
    			
            }
    
            @Override
            public void onPrintersInvalid() {
                mPrinterHolders.clear();
                notifyDataSetInvalidated();
            }
    
            public PrinterHolder getPrinterHolder(PrinterId printerId) {
                final int itemCount = getCount();
                for (int i = 0; i < itemCount; i++) {
                    Object item = getItem(i);
                    if (item instanceof PrinterHolder) {
                        PrinterHolder printerHolder = (PrinterHolder) item;
                        if (printerId.equals(printerHolder.printer.getId())) {
                            return printerHolder;
                        }
                    }
                }
                return null;
            }
    
            /**
             * Remove a printer from the holders if it is marked as removed.
             *
             * @param printerId the id of the printer to remove.
             *
             * @return true iff the printer was removed.
             */
            public boolean pruneRemovedPrinter(PrinterId printerId) {
                final int holderCounts = mPrinterHolders.size();
                for (int i = holderCounts - 1; i >= 0; i--) {
                    PrinterHolder printerHolder = mPrinterHolders.get(i);
    
                    if (printerHolder.printer.getId().equals(printerId) && printerHolder.removed) {
                        mPrinterHolders.remove(i);
                        return true;
                    }
                }
    
                return false;
            }
    
    		//gatsby addPrinters
            private void addPrinters(List<PrinterHolder> list, Collection<PrinterInfo> printers) {
                for (PrinterInfo printer : printers) {
                    PrinterHolder printerHolder = new PrinterHolder(printer);
                    list.add(printerHolder);
                }
            }
    
            private PrinterInfo createFakePdfPrinter() {
                ArraySet<MediaSize> allMediaSizes = MediaSize.getAllPredefinedSizes();
                MediaSize defaultMediaSize = MediaSizeUtils.getDefault(PrintActivity.this);
    
                PrinterId printerId = new PrinterId(getComponentName(), "PDF printer");
    
                PrinterCapabilitiesInfo.Builder builder =
                        new PrinterCapabilitiesInfo.Builder(printerId);
    
                final int mediaSizeCount = allMediaSizes.size();
                for (int i = 0; i < mediaSizeCount; i++) {
                    MediaSize mediaSize = allMediaSizes.valueAt(i);
                    builder.addMediaSize(mediaSize, mediaSize.equals(defaultMediaSize));
                }
    
                builder.addResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300),
                        true);
                builder.setColorModes(PrintAttributes.COLOR_MODE_COLOR
                        | PrintAttributes.COLOR_MODE_MONOCHROME, PrintAttributes.COLOR_MODE_COLOR);
    
                return new PrinterInfo.Builder(printerId, getString(R.string.save_as_pdf),
                        PrinterInfo.STATUS_IDLE).setCapabilities(builder.build()).build();
            }
        }
    
    	//Gatsby DestinationAdapter  Adapter End
    
        private final class PrintersObserver extends DataSetObserver {
            @Override
            public void onChanged() {
                PrinterInfo oldPrinterState = mCurrentPrinter;
                if (oldPrinterState == null) {
                    return;
                }
    			
    			Log.d("gatsby","PrintersObserver oldPrinterState.getId()-> "+oldPrinterState.getId());
                PrinterHolder printerHolder = mDestinationSpinnerAdapter.getPrinterHolder(
                        oldPrinterState.getId());
                PrinterInfo newPrinterState = printerHolder.printer;
    
                if (printerHolder.removed) {
                    onPrinterUnavailable(newPrinterState);
                }
    
                /*if (mDestinationSpinner.getSelectedItem() != printerHolder) {
                    mDestinationSpinner.setSelection(
                            mDestinationSpinnerAdapter.getPrinterIndex(newPrinterState.getId()));
                }*/
    			Log.d("gatsby","PrintersObserver printer_flag -> "+printer_flag +" xh_printer_id ->"+xh_printer_id);	
    			if (printer_flag) {				
    				mDestinationSpinner.setSelection(xh_printer_id);							
                }else {
                    mDestinationSpinner.setSelection(
                            mDestinationSpinnerAdapter.getPrinterIndex(newPrinterState.getId()));				
    			}
    
                if (oldPrinterState.equals(newPrinterState)) {
                    return;
                }
    
                PrinterCapabilitiesInfo oldCapab = oldPrinterState.getCapabilities();
                PrinterCapabilitiesInfo newCapab = newPrinterState.getCapabilities();
    
                final boolean hadCabab = oldCapab != null;
                final boolean hasCapab = newCapab != null;
                final boolean gotCapab = oldCapab == null && newCapab != null;
                final boolean lostCapab = oldCapab != null && newCapab == null;
                final boolean capabChanged = capabilitiesChanged(oldCapab, newCapab);
    
                final int oldStatus = oldPrinterState.getStatus();
                final int newStatus = newPrinterState.getStatus();
    
                final boolean isActive = newStatus != PrinterInfo.STATUS_UNAVAILABLE;
                final boolean becameActive = (oldStatus == PrinterInfo.STATUS_UNAVAILABLE
                        && oldStatus != newStatus);
                final boolean becameInactive = (newStatus == PrinterInfo.STATUS_UNAVAILABLE
                        && oldStatus != newStatus);
    
                mPrinterAvailabilityDetector.updatePrinter(newPrinterState);
    
                mCurrentPrinter = newPrinterState;
    
                final boolean updateNeeded = ((capabChanged && hasCapab && isActive)
                        || (becameActive && hasCapab) || (isActive && gotCapab));
    
                if (capabChanged && hasCapab) {
                    updatePrintAttributesFromCapabilities(newCapab);
                }
    
                if (updateNeeded) {
                    updatePrintPreviewController(false);
                }
    
                if ((isActive && gotCapab) || (becameActive && hasCapab)) {
                    onPrinterAvailable(newPrinterState);
                } else if ((becameInactive && hadCabab) || (isActive && lostCapab)) {
                    onPrinterUnavailable(newPrinterState);
                }
    
                if (updateNeeded && canUpdateDocument()) {
                    updateDocument(false);
                }
    
                // Force a reload of the enabled print services to update mAdvancedPrintOptionsActivity
                // in onLoadFinished();
                getLoaderManager().getLoader(LOADER_ID_ENABLED_PRINT_SERVICES).forceLoad();
    
                updateOptionsUi();
                updateSummary();
            }
    
            private boolean capabilitiesChanged(PrinterCapabilitiesInfo oldCapabilities,
                    PrinterCapabilitiesInfo newCapabilities) {
                if (oldCapabilities == null) {
                    if (newCapabilities != null) {
                        return true;
                    }
                } else if (!oldCapabilities.equals(newCapabilities)) {
                    return true;
                }
                return false;
            }
        }
    
        private final class MyOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
            @Override
            public void onItemSelected(AdapterView<?> spinner, View view, int position, long id) {
                boolean clearRanges = false;
    
                if (spinner == mDestinationSpinner) {
                    if (position == AdapterView.INVALID_POSITION) {
                        return;
                    }
    
                    if (id == DEST_ADAPTER_ITEM_ID_MORE) {
                        startSelectPrinterActivity();
                        return;
                    }
    				
    				//gatsby  currentPrinter
                    PrinterHolder currentItem = (PrinterHolder) mDestinationSpinner.getSelectedItem();
                    PrinterInfo currentPrinter = (currentItem != null) ? currentItem.printer : null;
    
                    // Why on earth item selected is called if no selection changed.
                    if (mCurrentPrinter == currentPrinter) {
                        return;
                    }
    
                    PrinterId oldId = null;
                    if (mCurrentPrinter != null) {
                        oldId = mCurrentPrinter.getId();
                    }
    
                    mCurrentPrinter = currentPrinter;
    
                    if (oldId != null) {
                        boolean printerRemoved = mDestinationSpinnerAdapter.pruneRemovedPrinter(oldId);
    
                        if (printerRemoved) {
                            // Trigger PrinterObserver.onChanged to adjust selection. This will call
                            // this function again.
                            mDestinationSpinnerAdapter.notifyDataSetChanged();
                            return;
                        }
                    }
    
                    PrinterHolder printerHolder = mDestinationSpinnerAdapter.getPrinterHolder(
                            currentPrinter.getId());
                    if (!printerHolder.removed) {
                        setState(STATE_CONFIGURING);
                        ensurePreviewUiShown();
                    }
    
                    mPrintJob.setPrinterId(currentPrinter.getId());
                    mPrintJob.setPrinterName(currentPrinter.getName());
    
                    mPrinterRegistry.setTrackedPrinter(currentPrinter.getId());
    
                    PrinterCapabilitiesInfo capabilities = currentPrinter.getCapabilities();
                    if (capabilities != null) {
                        updatePrintAttributesFromCapabilities(capabilities);
                    }
    
                    mPrinterAvailabilityDetector.updatePrinter(currentPrinter);
    
                    // Force a reload of the enabled print services to update
                    // mAdvancedPrintOptionsActivity in onLoadFinished();
                    getLoaderManager().getLoader(LOADER_ID_ENABLED_PRINT_SERVICES).forceLoad();
                } else if (spinner == mMediaSizeSpinner) {
                    SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(position);
                    PrintAttributes attributes = mPrintJob.getAttributes();
    
                    MediaSize newMediaSize;
                    if (mOrientationSpinner.getSelectedItemPosition() == 0) {
                        newMediaSize = mediaItem.value.asPortrait();
                    } else {
                        newMediaSize = mediaItem.value.asLandscape();
                    }
    
                    if (newMediaSize != attributes.getMediaSize()) {
                        clearRanges = true;
                        attributes.setMediaSize(newMediaSize);
                    }
                } else if (spinner == mColorModeSpinner) {
                    SpinnerItem<Integer> colorModeItem = mColorModeSpinnerAdapter.getItem(position);
                    mPrintJob.getAttributes().setColorMode(colorModeItem.value);
                } else if (spinner == mDuplexModeSpinner) {
                    SpinnerItem<Integer> duplexModeItem = mDuplexModeSpinnerAdapter.getItem(position);
                    mPrintJob.getAttributes().setDuplexMode(duplexModeItem.value);
                } else if (spinner == mOrientationSpinner) {
                    SpinnerItem<Integer> orientationItem = mOrientationSpinnerAdapter.getItem(position);
                    PrintAttributes attributes = mPrintJob.getAttributes();
                    if (mMediaSizeSpinner.getSelectedItem() != null) {
                        boolean isPortrait = attributes.isPortrait();
    
                        if (isPortrait != (orientationItem.value == ORIENTATION_PORTRAIT)) {
                            clearRanges = true;
                            if (orientationItem.value == ORIENTATION_PORTRAIT) {
                                attributes.copyFrom(attributes.asPortrait());
                            } else {
                                attributes.copyFrom(attributes.asLandscape());
                            }
                        }
                    }
                } else if (spinner == mRangeOptionsSpinner) {
                    if (mRangeOptionsSpinner.getSelectedItemPosition() == 0) {
                        clearRanges = true;
                        mPageRangeEditText.setText("");
                    } else if (TextUtils.isEmpty(mPageRangeEditText.getText())) {
                        mPageRangeEditText.setError("");
                    }
                }
    
                if (clearRanges) {
                    clearPageRanges();
                }
    
                updateOptionsUi();
    
                if (canUpdateDocument()) {
                    updateDocument(false);
                }
            }
    
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                /* do nothing*/
            }
        }
    
        private final class SelectAllOnFocusListener implements OnFocusChangeListener {
            @Override
            public void onFocusChange(View view, boolean hasFocus) {
                EditText editText = (EditText) view;
                if (!TextUtils.isEmpty(editText.getText())) {
                    editText.setSelection(editText.getText().length());
                }
    
                if (view == mPageRangeEditText && !hasFocus && mPageRangeEditText.getError() == null) {
                    updateSelectedPagesFromTextField();
                }
            }
        }
    
        private final class RangeTextWatcher implements TextWatcher {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                /* do nothing */
            }
    
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                /* do nothing */
            }
    
            @Override
            public void afterTextChanged(Editable editable) {
                final boolean hadErrors = hasErrors();
    
                PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
                final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
                PageRange[] ranges = PageRangeUtils.parsePageRanges(editable, pageCount);
    
                if (ranges.length == 0) {
                    if (mPageRangeEditText.getError() == null) {
                        mPageRangeEditText.setError("");
                        updateOptionsUi();
                    }
                    return;
                }
    
                if (mPageRangeEditText.getError() != null) {
                    mPageRangeEditText.setError(null);
                    updateOptionsUi();
                }
    
                if (hadErrors && canUpdateDocument()) {
                    updateDocument(false);
                }
            }
        }
    
        private final class EditTextWatcher implements TextWatcher {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                /* do nothing */
            }
    
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                /* do nothing */
            }
    
            @Override
            public void afterTextChanged(Editable editable) {
                final boolean hadErrors = hasErrors();
    
                if (editable.length() == 0) {
                    if (mCopiesEditText.getError() == null) {
                        mCopiesEditText.setError("");
                        updateOptionsUi();
                    }
                    return;
                }
    
                int copies = 0;
                try {
                    copies = Integer.parseInt(editable.toString());
                } catch (NumberFormatException nfe) {
                    /* ignore */
                }
    
                if (copies < MIN_COPIES) {
                    if (mCopiesEditText.getError() == null) {
                        mCopiesEditText.setError("");
                        updateOptionsUi();
                    }
                    return;
                }
    
                mPrintJob.setCopies(copies);
    
                if (mCopiesEditText.getError() != null) {
                    mCopiesEditText.setError(null);
                    updateOptionsUi();
                }
    
                if (hadErrors && canUpdateDocument()) {
                    updateDocument(false);
                }
            }
        }
    
        private final class ProgressMessageController implements Runnable {
            private static final long PROGRESS_TIMEOUT_MILLIS = 1000;
    
            private final Handler mHandler;
    
            private boolean mPosted;
    
            /** State before run was executed */
            private int mPreviousState = -1;
    
            public ProgressMessageController(Context context) {
                mHandler = new Handler(context.getMainLooper(), null, false);
            }
    
            public void post() {
                if (mState == STATE_UPDATE_SLOW) {
                    setState(STATE_UPDATE_SLOW);
                    ensureProgressUiShown();
                    updateOptionsUi();
    
                    return;
                } else if (mPosted) {
                    return;
                }
                mPreviousState = -1;
                mPosted = true;
                mHandler.postDelayed(this, PROGRESS_TIMEOUT_MILLIS);
            }
    
            private int getStateAfterCancel() {
                if (mPreviousState == -1) {
                    return mState;
                } else {
                    return mPreviousState;
                }
            }
    
            public int cancel() {
                int state;
    
                if (!mPosted) {
                    state = getStateAfterCancel();
                } else {
                    mPosted = false;
                    mHandler.removeCallbacks(this);
    
                    state = getStateAfterCancel();
                }
    
                mPreviousState = -1;
    
                return state;
            }
    
            @Override
            public void run() {
                mPosted = false;
                mPreviousState = mState;
                setState(STATE_UPDATE_SLOW);
                ensureProgressUiShown();
                updateOptionsUi();
            }
        }
    
        private static final class DocumentTransformer implements ServiceConnection {
            private static final String TEMP_FILE_PREFIX = "print_job";
            private static final String TEMP_FILE_EXTENSION = ".pdf";
    
            private final Context mContext;
    
            private final MutexFileProvider mFileProvider;
    
            private final PrintJobInfo mPrintJob;
    
            private final PageRange[] mPagesToShred;
    
            private final PrintAttributes mAttributesToApply;
    
            private final Runnable mCallback;
    
            public DocumentTransformer(Context context, PrintJobInfo printJob,
                    MutexFileProvider fileProvider, PrintAttributes attributes,
                    Runnable callback) {
                mContext = context;
                mPrintJob = printJob;
                mFileProvider = fileProvider;
                mCallback = callback;
                mPagesToShred = computePagesToShred(mPrintJob);
                mAttributesToApply = attributes;
            }
    
            public void transform() {
                // If we have only the pages we want, done.
                if (mPagesToShred.length <= 0 && mAttributesToApply == null) {
                    mCallback.run();
                    return;
                }
    
                // Bind to the manipulation service and the work
                // will be performed upon connection to the service.
                Intent intent = new Intent(PdfManipulationService.ACTION_GET_EDITOR);
                intent.setClass(mContext, PdfManipulationService.class);
                mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
            }
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                final IPdfEditor editor = IPdfEditor.Stub.asInterface(service);
                new AsyncTask<Void, Void, Void>() {
                    @Override
                    protected Void doInBackground(Void... params) {
                        // It's OK to access the data members as they are
                        // final and this code is the last one to touch
                        // them as shredding is the very last step, so the
                        // UI is not interactive at this point.
                        doTransform(editor);
                        updatePrintJob();
                        return null;
                    }
    
                    @Override
                    protected void onPostExecute(Void aVoid) {
                        mContext.unbindService(DocumentTransformer.this);
                        mCallback.run();
                    }
                }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                /* do nothing */
            }
    
            private void doTransform(IPdfEditor editor) {
                File tempFile = null;
                ParcelFileDescriptor src = null;
                ParcelFileDescriptor dst = null;
                InputStream in = null;
                OutputStream out = null;
                try {
                    File jobFile = mFileProvider.acquireFile(null);
                    src = ParcelFileDescriptor.open(jobFile, ParcelFileDescriptor.MODE_READ_WRITE);
    
                    // Open the document.
                    editor.openDocument(src);
    
                    // We passed the fd over IPC, close this one.
                    src.close();
    
                    // Drop the pages.
                    editor.removePages(mPagesToShred);
    
                    // Apply print attributes if needed.
                    if (mAttributesToApply != null) {
                        editor.applyPrintAttributes(mAttributesToApply);
                    }
    
                    // Write the modified PDF to a temp file.
                    tempFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_EXTENSION,
                            mContext.getCacheDir());
                    dst = ParcelFileDescriptor.open(tempFile, ParcelFileDescriptor.MODE_READ_WRITE);
                    editor.write(dst);
                    dst.close();
    
                    // Close the document.
                    editor.closeDocument();
    
                    // Copy the temp file over the print job file.
                    jobFile.delete();
                    in = new FileInputStream(tempFile);
                    out = new FileOutputStream(jobFile);
                    Streams.copy(in, out);
                } catch (IOException|RemoteException e) {
                    Log.e(LOG_TAG, "Error dropping pages", e);
                } finally {
                    IoUtils.closeQuietly(src);
                    IoUtils.closeQuietly(dst);
                    IoUtils.closeQuietly(in);
                    IoUtils.closeQuietly(out);
                    if (tempFile != null) {
                        tempFile.delete();
                    }
                    mFileProvider.releaseFile();
                }
            }
    
            private void updatePrintJob() {
                // Update the print job pages.
                final int newPageCount = PageRangeUtils.getNormalizedPageCount(
                        mPrintJob.getPages(), 0);
                mPrintJob.setPages(new PageRange[]{PageRange.ALL_PAGES});
    
                // Update the print job document info.
                PrintDocumentInfo oldDocInfo = mPrintJob.getDocumentInfo();
                PrintDocumentInfo newDocInfo = new PrintDocumentInfo
                        .Builder(oldDocInfo.getName())
                        .setContentType(oldDocInfo.getContentType())
                        .setPageCount(newPageCount)
                        .build();
    
                File file = mFileProvider.acquireFile(null);
                try {
                    newDocInfo.setDataSize(file.length());
                } finally {
                    mFileProvider.releaseFile();
                }
    
                mPrintJob.setDocumentInfo(newDocInfo);
            }
    
            private static PageRange[] computePagesToShred(PrintJobInfo printJob) {
                List<PageRange> rangesToShred = new ArrayList<>();
                PageRange previousRange = null;
    
                PageRange[] printedPages = printJob.getPages();
    			if(printedPages != null && printedPages.length != 0){
                final int rangeCount = printedPages.length;
                for (int i = 0; i < rangeCount; i++) {
                    PageRange range = printedPages[i];
    
                    if (previousRange == null) {
                        final int startPageIdx = 0;
                        final int endPageIdx = range.getStart() - 1;
                        if (startPageIdx <= endPageIdx) {
                            PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
                            rangesToShred.add(removedRange);
                        }
                    } else {
                        final int startPageIdx = previousRange.getEnd() + 1;
                        final int endPageIdx = range.getStart() - 1;
                        if (startPageIdx <= endPageIdx) {
                            PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
                            rangesToShred.add(removedRange);
                        }
                    }
    
                    if (i == rangeCount - 1) {
                        if (range.getEnd() != Integer.MAX_VALUE) {
                            rangesToShred.add(new PageRange(range.getEnd() + 1, Integer.MAX_VALUE));
                        }
                    }
    
                    previousRange = range;
                }
    			}
    
                PageRange[] result = new PageRange[rangesToShred.size()];
                rangesToShred.toArray(result);
                return result;
            }
        }
    }
    

     3.2. 惠普打印机 cp /mmt/sdcard/test.pdf /dev/usb/lp0  调出/dev/usb/lp0 节点  

    --- a/system/core/init/devices.cpp
    +++ b/system/core/init/devices.cpp
    @@ -699,10 +699,17 @@ static void handle_generic_device_event(struct uevent *uevent)
                      make_dir(devpath, 0755);
                      snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id);
                  }
    -         }else if (!strncmp(uevent->subsystem, "usbmisc", 7)) {  
    -							base = "/dev/";     
    -				 }
    -				  else {
    +         }else if (!strncmp(uevent->subsystem, "usbmisc", 7)) { 
    +			ERROR("gatsby uevent->subsystem is %s\n",uevent->subsystem);
    +			ERROR("gatsby uevent->device_name is %s\n",uevent->device_name);
    +				if(!strncmp(uevent->device_name,"usb/lp",6)){
    +					base = "/dev/usb/";
    +					make_dir(base, 0755);	
    +				}else{
    +					return;
    +				}			   
    +		
    +		} else {
                  /* ignore ot
    

      

      

  • 相关阅读:
    微信发送模板消息
    主从复制 读写分离
    php nginx反向代理
    go开发工具goclipse的安装
    安装go1.11.2
    基于科大讯飞AIUI平台自定义语义库的开发
    转载--php 7.2 安装 mcrypt 扩展
    mysql取出字段数据的精度
    sublime 2 格式化json
    RESTful接口需知道
  • 原文地址:https://www.cnblogs.com/crushgirl/p/15567400.html
Copyright © 2011-2022 走看看